2015-10-06 210 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