2013-06-18 11 views
16

Rozważmy następujący program:g ++ - 4.8.1 uważa, że ​​jawnie deklarowane destructor bez specyfikacji wyjątków jest zawsze noexcept (true)

#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"); 

Z g++-4.8.1, jest statyczna awarii twierdzenie na Explicit - wydaje się, że ~Explicit() jest noexcept. To nie pasuje do moich oczekiwań. Według §12.4.3:

Deklaracja destruktora, że ​​nie ma wyjątków specyfikacją jest niejawnie uważany mieć taki sam wyjątek specyfikacją jako dorozumiane oświadczenie

Najśmieszniejsze tutaj kontrola Implicit wydaje się zachowywać zgodnie z moją interpretacją § 15.4.14 (poprzez §12.4.7).

... Jeśli f jest ... ... to destruktor niejawny wyjątek-specyfikacja określa ... f ma wyjątku specyfikacją noexcept(true) jeśli każda funkcja pozwala ona bezpośrednio wywołuje żadnych wyjątków.

g++-4.7 brakuje is_nothrow_destructable, napisałem mój własny, aby sprawdzić zachowanie w 4.7. Program wydaje się kompilować idealnie dobrze. Zastrzegam sobie prawo do tego, aby być całkowicie błędne i źródłem mojego zamieszania:

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

TL; DR: Dlaczego g++-4.8.1 myśleć, że jawnie deklarowane destructor bez specyfikacji wyjątków jest zawszenoexcept(true)?


Aktualizacja: Otworzyłem błąd na ten temat: 57645. Jeśli naprawdę potrzebujesz obejść ten problem, możesz dodać specyfikację wyjątku do destruktora (na przykład w przykładzie: Thrower).

+0

W ten sposób Andy Prowl napisał odpowiedź z ponad 1000 upvotes. –

+0

@ H2CO3: lol, nie, po prostu myślę, że to jest błąd kompilatora i mam zero szansy, aby powiedzieć coś istotnego na ten temat;) –

Odpowiedz

7

TL; DR: Dlaczego g ++ - 4.8.1 myśleć, że jawnie deklarowane destructor bez specyfikacji wyjątków jest zawsze noexcept(true)?

Ponieważ ma błąd?

Twoja interpretacja normy jest poprawna, a Clang implementuje ją poprawnie (aserser nie uruchamia się).

f ma wyjątku specyfikacją noexcept(true) jeśli każda funkcja bezpośrednio wywołuje pozwala bez wyjątków.

Destruktor bezpośrednio wywołuje destruktor wszystkich podobiektów:

§12.4 [class.dtor] p8:

Po wykonaniu ciało destruktora i niszczenia wszelkich automatycznych obiekty przydzielone w organizmie, destruktor dla klasy X wywołuje destruktory dla bezpośrednich nie-zmiennych nieliniowych elementów danych X, [...].

+2

O tak, proszę złożyć zgłoszenie błędu [w GCC's bugtracker] (http: // gcc. gnu.org/bugzilla/). – Xeo

+0

Miałem nadzieję, że się myliłem, zamiast kompilatora ... jest to o wiele wygodniejsze. Otworzyłem błąd. –