2015-10-06 11 views
5

Il codice seguente attiva static_assert anche se non credo che dovrebbe:strano comportamento di std :: is_nothrow_destructible

#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() 
{ 
} 

quando viene compilato con:

g++-4.9 -std=c++11 nothrow_destructible_bug.cc 

accade quanto segue:

nothrow_destructible_bug.cc:20:1: error: static assertion failed: That's odd 
static_assert(std::is_nothrow_destructible<Foo>::value, "That's odd"); 
^ 

Come mai utilizzare semplicemente Foo per creare un'istanza di un modello in una classe non correlata, perde lo stato noexcept? Ho pensato che fosse un bug del compilatore, ma l'ho provato con tutte le versioni recenti di gcc e clang e sembrano dare lo stesso errore.

+0

Intendevi controllare 'is_nothrow_destructible < Bar >' invece di 'is_nothrow_destructible < Foo >'? –

risposta

4

Dove si utilizza Tmp<Foo> xx, Foo è un tipo incompleto. Ciò viola una delle condizioni preliminari per l'uso di is_nothrow_destructible e il suo utilizzo è un comportamento non definito. Una possibilità di tale UB è per is_nothrow_destructible essere falsa.

Commentando l'uso di Tmp si eviterà questo problema. Poiché il modello non viene istanziato fino a quando non viene utilizzato, anche il commento del costruttore eviterà il problema poiché il modello non verrà ancora istanziato.

Spostare la definizione di struct Foo prima del Bar dovrebbe inoltre evitare il problema.

+0

"is_nothrow_destructable [sic] sarà falso." È semplicemente UB. Tutto può succedere. –

+0

Mi chiedo quali sono queste condizioni e dove potrei leggere su di loro? Il fatto che ci sia un UB silenzioso in questo caso mi spaventa – dragonroot

+0

@dragonroot Sono tutti nel documento standard della lingua. Se la tua documentazione per is_nothrow_destructible non menziona che il tipo deve essere un tipo completo, devi inviarci un rapporto sui difetti. – 1201ProgramAlarm