2016-03-04 7 views
12

Ich bin mir nicht sicher, ob es ein Fehler des GCC Compiler oder das beabsichtigte Verhalten von noexcept ist.
Betrachten Sie das folgende Beispiel:noexcept, erben Konstruktoren und die ungültige Verwendung eines unvollständigen Typs, der tatsächlich abgeschlossen ist

struct B { 
    B(int) noexcept { } 
    virtual void f() = 0; 
}; 

struct D: public B { 
    using B::B; 
    D() noexcept(noexcept(D{42})): B{42} { } 
    void f() override { } 
}; 

int main() { 
    B *b = new D{}; 
} 

Wenn die noexcept entfernt wird, kompiliert.
Wie auch immer, wie es in dem Beispiel ist, habe ich diesen Fehler von GCC V5.3.1:

test.cpp:8:31: error: invalid use of incomplete type ‘struct D’ 
    D() noexcept(noexcept(D{42})): B{42} { } 
          ^

Soweit ich weiß, struct D ist nicht ein unvollständiger Typ, sondern erben Konstrukteuren in der Erklärung beteiligt und Es sieht so aus, als ob der Compiler tatsächlich die Vollständigkeit der Basisstruktur B mehr als von berücksichtigt.

Ist das das beabsichtigte Verhalten oder ist es legaler Code?

Aus Gründen der Klarheit:

  • here die Kompilierung erfolgreich mit Klirren 3.7.1
  • here die Kompilierung GCC 5.3.0

this link Siehe nicht mit zu Die Bugzilla für den GCC-Compiler für weitere Details.
Derzeit ist der Fehler immer noch nicht bestätigt. Ich werde die Frage so bald wie möglich aktualisieren.

+0

Hmm, Clang 3.7.1 akzeptiert diesen Code. Ich wette, das ist ein GCC-Bug. – thirtythreeforty

+0

Ja, für mich hört sich das viel mehr wie ein Fehler im GCC-Compiler an, aber es könnte auch ein Bug im Klirren sein !! Ich bin mir nicht sicher, ob es ein gültiger Code ist, auch wenn es für mich in Ordnung ist. Ein Sprachanwalt würde hier helfen. :-) – skypjack

+0

Ich habe den Ort hinzugefügt, über den sich der Compiler beschwert, zusammen mit einer definitiven Version für zukünftige Googler (der neueste stabile GCC zum Zeitpunkt des Schreibens). – thirtythreeforty

Antwort

12

Ihr Code ist legal, obwohl GCC das Gegenteil behauptet. Es nimmt Anstoß an dieser lustigen schau Erklärung:

D() noexcept(noexcept(D{42})); 

Die äußerste noexcept ein noexcept specifier ist, die besagen, dass D::D() noexcept ist, wenn und nur wenn sein Konstant Argument Ausdruck true ergibt. Der innere noexcept ist ein noexcept operator, der zur Kompilierzeit prüft, ob sein Argumentausdruck, der nicht tatsächlich ausgewertet wird, keine Ausnahmen auslöst. Da D::D(int) kein Ausnahmewert ist (von B geerbt), sollte dies der Fall sein.

cppreference.com stellt ausdrücklich fest, dass der Bediener innerhalb des Spezifikations ist zugelassen (Hervorhebung hinzugefügt):

Der noexcept Operator führt eine Kompilierung-Prüfung, die true zurückgibt, wenn ein Ausdruck deklariert wird nicht werfen Ausnahmen.

Es kann im noexcept-Bezeichner einer Funktionsschablone verwendet werden, um zu deklarieren, dass die Funktion Ausnahmen für einige Typen, aber nicht für andere Typen auslöst.

nun die Klasse sollte aufgrund §9.2 komplette im noexcept Spezifizierer betrachtet werden.2 der Standard (bold Hervorhebung hinzugefügt):

eine Klasse einen vollständig definierte Objekttyp angesehen wird (3,9) (oder vollständigen Typen) auf dem Abschluss } des Klasse-Spezifizierer. Innerhalb der Klasse Mitglied-Spezifikation, wird die Klasse als vollständig innerhalb Funktionsrümpfe, Standardargumente betrachtet, mit Deklaration s inheriting Bauer (12.9) die Einführung, Ausnahme-Spezifikation s und brace- or-equal-initializer s für nicht statische Datenelemente (einschließlich solcher Objekte in verschachtelten Klassen). Ansonsten wird es in seiner eigenen Klasse als Mitglied-Spezifikation als unvollständig angesehen.

§15.4.1 definiert eine exception-Spezifikation als die folgende Grammatik:

exception-Spezifikation:

  • dynamic-Ausnahme-Spezifikation

  • noexcept-Spezifikation

So sollten GCC Code nicht ablehnen.

+0

Zum jetzigen Zeitpunkt sehe ich kein GCC-Ticket für dieses spezielle Problem. Vielleicht könntest du einen einreichen? – thirtythreeforty

+0

Ich werde es hinzufügen. [Hier] (https://gcc.gnu.org/bugzilla), oder? – skypjack

+0

Ich denke schon, ja! Sie könnten sich mit dieser Antwort verbinden oder relevante Bits kopieren (meistens die zweite Hälfte). – thirtythreeforty

Verwandte Themen