2017-02-03 2 views
1

Nehmen Sie dieses einfache Beispiel.Das Erben des Standardkonstruktors schlägt in gcc fehl und funktioniert beim Clalhen, welcher hat den Fehler?

struct Base { 
    // Base::Base() defined by the compiler 
}; 

struct Derived: Base { 
    using Base::Base; // Should inherit Base::Base() 

    Derived(int value): 
     m_value(value) 
    {} 

private: 
    int m_value; // If Base::Base() is invoked, it's default constructed 
}; 

Derived t; 

Soweit ich durch das Lesen cppreference zu verstehen, sollte Derived den Standard Base::Base() Konstruktor erben und den obigen Code sollte glücklich kompilieren.

Edit: meine schlechte, erzählt die Seite, die ich verlinkt, genau das Gegenteil. Es scheint also, dass Clang eine Regression hat.

jedoch alle Versionen von gcc Ich habe versucht es nicht, beschweren, dass Derived keinen Standardkonstruktor hat, während Klirren tut es ganz gut, aber erst seit Version 3.9.0; g ++ - 7 segfaults, auch .

Sie können es selbst auf godbolt sehen.

Also, wer ist hier schuld? Clang für die Erlaubnis, oder GCC (Bar der Segfault) für nicht erlaubt?


Obwohl es so nur auf Godbolt zu tun scheint, kann ich die segfault lokal nicht reproduzieren.

+0

@Barry: Gute Arbeit, mein Schüler. (Beat mich, um Sekunden) –

+1

die cppreference Seite, die Sie verknüpft sagt, "Alle Kandidaten geerbt Konstruktoren * das sind nicht die Standard-Konstruktor *" usw. –

+0

Sie haben natürlich Recht, @ n.m., Meine schlechte. Aus einigen Gründen habe ich diesen Teil verpasst. –

Antwort

2

Erstens ist der Compiler segfault immer ein Compilerfehler. Sie sollten das melden.

Zweitens werden Standardkonstruktoren niemals geerbt. Von N3242 (der Wortlaut in N3797 ist ähnlich), [class.inhctor]:

Für jeden Nicht-Template-Konstruktor in dem Kandidatensatz von vererbten Konstrukteurs andere als ein Konstruktor mit keinen Parametern oder ein Kopieren/Verschieben Konstruktor mit einem einzelnen Parameter, ein Konstruktor wird implizit mit denselben Konstruktormerkmalen deklariert, es sei denn, es gibt einen von einem Benutzer deklarierten Konstruktor mit derselben Signatur in der Klasse, in der die using-Deklaration erscheint.

Der Standardkonstruktor von Base nicht in Derived vererbt wird, so sollte Derived t schlecht gebildet werden, da gibt es keinen gültigen Konstruktor unter Null Argumente.


In C++ 17 ist dies immer noch schlecht gebildet, obwohl die Formulierung anders ist. Noch [class.inhctor], von N4618:

Wenn ein Konstruktor für Typen B aufgerufen wird, ein Objekt von einem anderen Typ D initialisiert werden (das heißt, wenn der Konstruktor (7.3.3) geerbt wurde), wird eine Initialisierung geht so vor, als ob ein default-Standardkonstruktor verwendet wurde, um das D-Objekt und jedes Basisklassenunterobjekt zu initialisieren, von dem der Konstruktor geerbt wurde, mit der Ausnahme, dass das B-Unterobjekt durch den Aufruf des geerbten Konstruktors initialisiert wird.

Um Base::Base() aufzurufen, müssten wir mit Derived::Derived() beginnen. Aber es gibt keine Derived::Derived().

+0

Danke! Es scheint also, dass Clang eine Regression hat. Ich bin bereits auf dem Weg, einen Fehlerbericht für den Segfault einzureichen, aber das passiert nur auf godbolt. Ich sollte auch einen Bug für den Klang einreichen. –

Verwandte Themen