以下代码触发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,它们似乎都给出了同样的错误。
答案 0 :(得分:4)
使用Tmp< Foo > xx
的地方,Foo
是不完整的类型。这违反了使用is_nothrow_destructible
的前提条件之一,其使用是未定义的行为。 UB的一种可能性是is_nothrow_destructible
为假。
评论Tmp的使用将避免这个问题。由于模板在使用之前没有实例化,因此注释掉构造函数也可以避免这个问题,因为模板还没有被实例化。
在struct Foo
之前移动Bar
的定义也应避免此问题。