C++ std::的奇怪行为是不可破坏的吗

C++ std::的奇怪行为是不可破坏的吗,c++,c++11,exception,exception-handling,C++,C++11,Exception,Exception Handling,以下代码触发了static\u 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

以下代码触发了
static\u 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()
{
}
发生以下情况:

nothrow_destructible_bug.cc:20:1: error: static assertion failed: That's odd
 static_assert( std::is_nothrow_destructible< Foo >::value, "That's odd" );
 ^
nothrow\u destructible\u bug.cc:20:1:错误:静态断言失败:这很奇怪
静态断言(std::是可破坏的::值,“这很奇怪”);
^

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

在使用
Tmpxx
时,
Foo
是一个不完整的类型。这违反了使用
的一个先决条件是\u nothrow\u destructible
,并且它的使用是未定义的行为。UB的一种可能性是,
不可破坏
为假

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


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

你的意思是检查
是否可破坏
而不是
是否可破坏
?“是否可破坏[sic]将是错误的。”它只是简单的UB。任何事情都有可能发生。我想知道这些情况是什么,我在哪里可以了解到它们?事实上,在这种情况下,有一个沉默的UB令人害怕me@dragonroot它们都在语言标准文档中。如果您的is_nothrow_destructible文档没有提到该类型需要是一个完整的类型,那么您应该为其提交一份缺陷报告。
nothrow_destructible_bug.cc:20:1: error: static assertion failed: That's odd
 static_assert( std::is_nothrow_destructible< Foo >::value, "That's odd" );
 ^