2010-05-14 14 views
27

Ich bemerkte vor kurzem eine Klasse in C++ 0x, die einen expliziten Standardkonstruktor aufruft. Es ist mir jedoch nicht möglich, ein Szenario zu entwerfen, in dem ein Standardkonstruktor implizit aufgerufen werden kann. Es scheint wie ein ziemlich sinnloser Spezifizierer. Ich dachte, vielleicht würde es Class c; für Class c = Class(); verbieten, aber das scheint nicht der Fall zu sein. zu navigieren [ähnlicher Text existiert in C++ 03, wenn nicht in den gleichen Orten]Zweck der expliziten Standardkonstruktoren

12.3.1.3

Einige relevanten Zitate aus dem C++ 0x FCD, da es einfacher ist für mich [ class.conv.ctor]

Ein Standardkonstruktor kann ein expliziter Konstruktor sein; Ein solcher Konstruktor wird verwendet, um eine Standard-Initialisierung oder -Wert-Initialisierung (8.5) durchzuführen.

Es wird ein Beispiel für einen expliziten Standardkonstruktor geliefert, aber es simuliert einfach das oben angegebene Beispiel.

8.5.6 [decl.init]

auf ein Objekt vom Typ T default-initialisieren bedeutet:

- wenn T ein (möglicherweise cv-qualifiziert) Klassentyp (Ziffer 9) Der Standardkonstruktor für T wird aufgerufen (und die Initialisierung ist fehlerhaft, wenn T keinen zugreifbaren Standardkonstruktor hat);

8.5.7 [decl.init]

Um Wert zu initialisieren bedeutet ein Objekt vom Typ T:

- wenn T ist eine (möglicherweise cv-qualifiziert) Klassentyp (Ziffer 9) mit einem Vom Benutzer bereitgestellter Konstruktor (12.1), dann wird der Standardkonstruktor für T aufgerufen (und die Initialisierung ist fehlerhaft, wenn T keinen zugänglichen Standardkonstruktor hat);

In beiden Fällen fordert der Standard den Aufruf des Standardkonstruktors. Aber das würde passieren, wenn der Standardkonstruktor nicht explizit wäre. Der Vollständigkeit halber:

8.5.11 [decl.init]

Wenn kein Initialisierer für ein Objekt angegeben wird, ist das Objekt default-initialisiert;

Von dem, was ich sagen kann, lässt dies nur Konvertierung von keinen Daten. Was keinen Sinn ergibt. Das Beste, was ich mit oben kommen kann wäre die folgende:

void function(Class c); 
int main() { 
    function(); //implicitly convert from no parameter to a single parameter 
} 

Aber offensichtlich ist das nicht die Art und Weise C++ Standardargumente verarbeitet. Was gibt es sonst noch dazu, dass sich explicit Class(); anders verhalten würde als Class();?

Das spezifische Beispiel, das diese Frage erzeugte, war std::function [20.8.14.2 func.wrap.func]. Es erfordert mehrere konvertierende Konstruktoren, von denen keiner explizit markiert ist, aber der Standardkonstruktor ist.

+0

Sobald ich auf Post klicke, denke ich, dass ich eine Erklärung gefunden habe. Aber ich warte auf die Bestätigung meiner Vermutungen, da dies sowieso eine nützliche Frage ist. –

Antwort

21

Dies erklärt einen expliziten Standardkonstruktors:

struct A { 
    explicit A(int a1 = 0); 
}; 

A a = 0; /* not allowed */ 
A b; /* allowed */ 
A c(0); /* allowed */ 

Falls es kein Parameter ist, wie im folgenden Beispiel, die explicit redundant ist.

struct A { 
    /* explicit is redundant. */ 
    explicit A(); 
}; 

In einigen C++ 0x Entwurf, ich glaube, es war n3035, machte es einen Unterschied in der folgenden Weise:

A a = {}; /* error! */ 
A b{}; /* alright */ 

void function(A a); 
void f() { function({}); /* error! */ } 

Aber in der FCD, sie changed this (obwohl ich vermute, dass Sie hatten diesen besonderen Grund nicht im Sinn, dass alle drei Fälle das entsprechende Objekt initialisieren. Die Wert-Initialisierung führt den Overload-Resolution-Tanz nicht durch und wird daher bei expliziten Konstruktoren nicht fehlschlagen.

+0

Okay. Dann ist der explizite Konstruktor für 'std :: function' einfach ein Übergriff von dieser Version des Entwurfs? Es war diese Erklärung, die ich nach dem Schreiben der Frage schließlich herausgefunden hatte, aber weder das mitgelieferte Beispiel noch 'std :: function()' verwendeten einen optionalen Parameter, so dass ich nicht ganz davon überzeugt war. –

+0

Dies scheint sich ein wenig geändert zu haben, siehe [CWG 1518] (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1518). Neuere Versionen von g ++ und clang ++ lehnen 'function ({})' für nicht-voreingestellte explizite Standardkonstruktoren ab, sogar im C++ 11-Modus. – dyp

+0

Siehe auch http://cplusplus.github.io/LWG/lwg-defects.html#2510 –