2015-04-07 7 views
12

Der Code:Programm mit "noexcept" Konstruktor von gcc akzeptiert, von Klirren abgelehnt

struct T { T() {} }; 

struct S 
{ 
    T t; 

    S() noexcept = default; 
}; 

int main() 
{ 
// S s; 
} 

g ++ 4.9.2 dies ohne Fehler oder Warnungen akzeptiert, klirrte jedoch 3.6 und 3.7 Bericht für Zeile 7:

error: exception specification of explicitly defaulted default constructor does not match the calculated one 

wenn jedoch die Leitung S s; nicht kommentiert geführt wird, g ++ 4.9.2 jetzt berichtet:

noex.cc: In function 'int main()': 
noex.cc:12:7: error: use of deleted function 'S::S()' 
    S s; 
    ^
noex.cc:7:5: note: 'S::S() noexcept' is implicitly deleted because its exception-specification does not match the implicit exception-specification '' 
    S() noexcept = default; 
    ^

Welcher Compiler ist richtig für den Originalcode?


Hintergrund:

g ++ selbst ermöglicht folgendes main hinzugefügt werden:

std::cout << std::is_constructible<S>::value << '\n'; 

die 0 ausgibt. Ich habe dieses Problem, wenn Klappern mit einigen komplizierten Code zu kompilieren, die starke Nutzung von Vorlagen, SFINAE und noexcept gemacht. In diesem Code S und T sind Template-Klassen; Das Verhalten hängt also davon ab, mit welchen Typen S instanziiert wurde. Clang lehnt es mit diesem Fehler für einige Arten, während g ++ es erlaubt und die SFINAE arbeiten nach is_constructible und ähnlichen Zügen.

+0

Weil im S-Konstruktor Sie Aufruf an T-Konstruktor bekommen, die jede Ausnahme werfen könnte.Clang ist richtig, glaube ich, –

+1

@SeverinPappadeux das ist wahr, über die Ausnahmen, aber das Problem scheint zu sein, ob der Code sofort zurückgewiesen werden sollte, oder ob der Effekt von '= default' darin besteht, * als gelöscht zu definieren * was g ++ zu tun scheint. –

Antwort

15

Abhängig von der Version des Standards Sie beraten.

N3337 [dcl.fct.def.default]/p2:

Eine explizit ausgefallene Funktion [...], eine explizite Ausnahme-Spezifikation haben nur, wenn es kompatibel ist (15.4) mit der Ausnahme spezifikations auf der impliziten Erklärung.

, die Ihren ursprünglichen Code schlecht formatiert.

Dies wurde von CWG issue 1778 zu lesen (N4296 [dcl.fct.def.default]/p3) geändert:

Wenn eine Funktion, die mit einer Ausnahme-Spezifikation deklariert wird die explizit vorbelegt ist nicht kompatibel (15.4) mit der Ausnahmebestimmung der impliziten Deklaration, dann wird

  • Wenn die Funktion explizit auf ihre erste Deklaration voreingestellt ist, wird sie als gelöscht definiert;
  • sonst wird das Programm schlecht ausgebildet.
  • was bedeutet, dass der Konstruktor jetzt nur als gelöscht definiert ist. (Der obige Wortlaut enthält Änderungen, die von N4285, einem Post-C++ 14-Papier, gemacht wurden, das einige Bereinigungsänderungen vornimmt, die rein redaktionell sein sollen. Die Version N3936 ist im Wesentlichen die gleiche.)

    Vermutlich GCC implementiert CWG1778-Auflösung, während Clang nicht.

    +0

    Welche Version erschien in veröffentlichten C++ 14? (clang 3.7 lehnt den Code immer noch mit -std = C++ 14 ab) –

    +0

    @MattMcNabb Das Problem hat den Status "C++ 14", daher sollte die zweite Version in C++ 14 sein. Beachten Sie, dass dies ein DR ist, so dass es wahrscheinlich auch im C++ 11-Modus implementiert wird. –

    +0

    @MattMcNabb 4296 ist so ziemlich was als C++ 14 modulo Tippfehler und so –