下面的代码触发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,他们似乎都给出了相同的错误。
发布于 2015-10-06 09:07:07
在使用Tmp< Foo > xx的情况下,Foo是不完整的类型。这违反了使用is_nothrow_destructible的前提条件之一,并且它的使用是未定义的行为。该UB的一种可能性是is_nothrow_destructible为假。
注释掉Tmp的使用可以避免这个问题。因为模板在使用之前不会被实例化,所以注释掉构造函数也可以避免这个问题,因为模板还没有被实例化。
将struct Foo的定义移到Bar之前也可以避免这个问题。
https://stackoverflow.com/questions/32960029
复制相似问题