【问题标题】:Strange behavior of std::is_nothrow_destructiblestd::is_nothrow_destructible 的奇怪行为
【发布时间】:2015-10-06 00:45:42
【问题描述】:

以下代码触发static_assert,尽管我认为它不应该:

#include <type_traits>

template< typename T >
struct Tmp
{
  ~Tmp() noexcept( std::is_nothrow_destructible< T >::value ) {}
};

struct Foo;

struct Bar
{
  // Comment this out for the problem to go away
  Tmp< Foo > xx;

  // ..or this
  Bar() {}
};

struct Foo {};

// This triggers
static_assert( std::is_nothrow_destructible< Foo >::value, "That's odd" );

int main()
{
}

编译时:

g++-4.9 -std=c++11 nothrow_destructible_bug.cc

会发生以下情况:

nothrow_destructible_bug.cc:20:1: error: static assertion failed: That's odd
 static_assert( std::is_nothrow_destructible< Foo >::value, "That's odd" );
 ^

为什么只使用Foo 实例化不相关类中的模板会使其失去noexcept 状态?我认为这是一个编译器错误,但我尝试了所有最新版本的 gcc 和 clang,它们似乎都给出了相同的错误。

【问题讨论】:

  • 您是不是要检查is_nothrow_destructible&lt; Bar &gt; 而不是is_nothrow_destructible&lt; Foo &gt;

标签: c++ c++11 exception exception-handling


【解决方案1】:

在你使用Tmp&lt; Foo &gt; xx 的地方,Foo 是一个不完整的类型。这违反了使用is_nothrow_destructible 的前提条件之一,它的使用是未定义的行为。该 UB 的一种可能性是 is_nothrow_destructible 为假。

注释掉 Tmp 的使用可以避免这个问题。由于模板在使用之前不会被实例化,因此将构造函数注释掉也将避免该问题,因为模板尚未被实例化。

struct Foo 的定义移到Bar 之前也应该可以避免这个问题。

【讨论】:

  • "is_nothrow_destructable [原文如此] 将是错误的。"简直是UB。任何事情都有可能发生。
  • 我想知道这些条件是什么,我可以从哪里了解到它们?在这种情况下有一个沉默的 UB 让我害怕
  • @dragonroot 它们都在语言标准文档中。如果您的 is_nothrow_destructible 文档没有提到该类型必须是完整的类型,您应该为其提交缺陷报告。
猜你喜欢
  • 2011-03-06
  • 2020-06-11
  • 2013-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多