2015-10-06 211 views
5

下面的代码触发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

您的意思是检查'is_nothrow_destructible < Bar >'而不是'is_nothrow_destructible < Foo >'? –

回答

4

您在哪里使用Tmp<Foo> xxFoo是不完整的类型。这违反了使用is_nothrow_destructible的前提条件之一,其使用是未定义的行为。 UB的一种可能性是is_nothrow_destructible是错误的。

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

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

+0

“is_nothrow_destructable [原文如此]将是错误的。”这只是UB。任何事情都可能发生。 –

+0

我想知道那些条件和我在哪里可以读到它们?在这种情况下,有一个无声的UB会吓到我 – dragonroot

+0

@dragonroot它们都在语言标准文档中。如果您的is_nothrow_destructible文档没有提及该类型需要是完整类型,则应提交缺陷报告。 – 1201ProgramAlarm