std :: is_nothrow_destructible的奇怪行为

dra*_*oot 5 c++ exception-handling exception c++11

以下代码触发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()
{
}
Run Code Online (Sandbox Code Playgroud)

编译时:

g++-4.9 -std=c++11 nothrow_destructible_bug.cc
Run Code Online (Sandbox Code Playgroud)

发生以下情况:

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

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

120*_*arm 4

您使用的地方Tmp< Foo > xx,Foo是不完整类型。这违反了使用 的前提条件之一is_nothrow_destructible,并且它的使用是未定义的行为。该 UB 的一种可能性是is_nothrow_destructible错误的。

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

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