2013-06-18 7 views
16

Si consideri il seguente programma:g ++ - 4.8.1 pensa che un distruttore esplicitamente dichiarata, senza specifica eccezione è sempre noexcept (vero)

#include <type_traits> 

struct Thrower 
{ 
    ~Thrower() noexcept(false) { throw 1; } 
}; 

struct Implicit 
{ 
    Thrower t; 
}; 
static_assert(!std::is_nothrow_destructible<Implicit>::value, "Implicit"); 

struct Explicit 
{ 
    ~Explicit() {} 

    Thrower t; 
}; 
static_assert(!std::is_nothrow_destructible<Explicit>::value, "Explicit"); 

Con g++-4.8.1, c'è un errore di asserzione statico sul Explicit - sembra pensare che ~Explicit() sia noexcept. Questo non corrisponde alle mie aspettative. Secondo §12.4.3:

Una dichiarazione di un distruttore che non ha una specifica delle eccezioni è implicitamente considerato di avere la stessa specifica delle eccezioni come una dichiarazione implicita

La cosa divertente ecco il controllo di Implicit sembra comportarsi secondo la mia interpretazione di §15.4.14 (tramite §12.4.7).

... Se f è un ... distruttore ... è implicita specifica delle eccezioni specifica ... f ha la specifica delle eccezioni noexcept(true) se ogni funzione si richiama direttamente non ammette eccezioni.

g++-4.7 manca is_nothrow_destructable, ho scritto il mio per controllare il comportamento in 4.7. Il programma sembra compilare perfettamente bene. Mi riservo il diritto per questo di essere completamente sbagliato e la fonte della mia confusione:

template <typename T> 
struct is_nothrow_destructible 
{ 
    static constexpr bool value = noexcept(std::declval<T>().~T()); 
}; 

TL; DR: Perché g++-4.8.1 pensa che un distruttore esplicitamente dichiarata, senza specifica eccezione è semprenoexcept(true)?


Aggiornamento: ho aperto un bug su questo: 57645. Se è davvero necessario aggirare questo problema, è possibile aggiungere una specifica di eccezione al distruttore (come nell'esempio Thrower).

+0

Ed è così che Andy Prowl ha scritto una risposta con 1000+ upvotes. –

+0

@ H2CO3: lol, no, penso solo che questo sia un bug del compilatore e non ho alcuna possibilità di dire nulla di rilevante al riguardo;) –

risposta

7

TL; DR: Perché g ++ - 4.8.1 pensa che un distruttore esplicitamente dichiarato con nessuna specifica di eccezione sia sempre noexcept(true)?

Perché ha un bug?

L'interpretazione dello standard è corretta e Clang lo implementa correttamente (l'asserzione non attiva).

f ha la specifica delle eccezioni noexcept(true) se ogni funzione invoca direttamente non ammette eccezioni.

Un distruttore invoca direttamente distruttore di tutti sottoggetti:

§12.4 [class.dtor] p8:

Dopo l'esecuzione del corpo del distruttore e distruggere qualsiasi oggetto automatici allocati all'interno del corpo, un distruttore per la classe X chiama i distruttori per i membri di dati non statici diretti non varianti di X, [...].

+2

Oh sì, per favore registra un bugreport [oltre al bugtracker di GCC] (http: // gcc. gnu.org/bugzilla/). – Xeo

+0

Speravo di sbagliare invece del compilatore ... è una cosa molto più comoda. Ho aperto un bug su di esso. –

Problemi correlati