Die Deklaration des implizit deklarierten Kopierkonstruktors wird nicht unterdrückt. Es wird einfach nicht wegen der Regeln der Überladungsauflösung aufgerufen. Der implizit deklarierte Kopierkonstruktor hat das Format Foo(const Foo&)
. Der wichtige Teil davon ist, dass es eine konstante Referenz braucht. Ihre Konstruktorvorlage verwendet eine nicht konstante Referenz.
a
ist nicht const, daher wird die nicht-const von einem Benutzer deklarierte Konstruktorvorlage dem implizit deklarierten Kopierkonstruktor vorgezogen. die implizit deklarierte Kopie Konstruktor aufzurufen, können Sie a
const machen:
const Foo a;
Foo b(a);
oder Sie static_cast
verwenden können, eine konstante Referenz auf a
zu erhalten:
Foo a;
Foo b(static_cast<const Foo&>(a));
Die Überladungsauflösung Regeln, die diese beschreiben sind gefunden meist in §13.3.3.2/3 der C++ 0x FCD. Dieses besondere Szenario mit einer Kombination aus L-Wert und rvalue Referenzen, ist eine Art von den verschiedenen Beispielen auf Seite 303.
A variadische Konstruktor Vorlage des implizit deklarierte Standardkonstruktors wird unterdrücken, weil eine variadische Konstruktor Vorlage Benutzer -declared und die implizit deklariert Standardkonstruktor wird nur zur Verfügung gestellt, wenn es keine Benutzer deklarierte Konstruktoren (C++ 0x FCD §12.1/5) sind:
wenn es X
, kein Benutzer deklarierten Konstruktor für die Klasse ist ein Konstruktor ohne Parameter wird implizit als Standard deklariert.
A variadische Konstruktor Vorlage wird die implizit deklariert Copykonstruktor nicht unterdrücken, da nur ein nicht-Template kann ein Konstruktor Copykonstruktor (§12.8/2, 3, 8 und C++ 0x FCD) sein:
eine nicht-Template-Konstruktor für Klasse X
ist eine Kopie Konstruktor, wenn seine erste Parameter vom Typ ist X&
, const X&
, volatile X&
oder const volatile X&
und entweder gibt es keine weiteren Parameter oder auch alle anderen Parameter Standardargumente haben.
Eine Nicht-Template-Konstruktor für Klasse X
ist ein Schritt Konstruktor, wenn seine erste Parameter vom Typ ist X&&
, const X&&
, volatile X&&
oder const volatile X&&
und entweder gibt es keine weiteren Parameter oder auch alle anderen Parameter Standardargumente haben.
Wenn die Klassendefinition keinen Kopierkonstruktor explizit deklariert und es keinen von Benutzern deklarierten Move-Konstruktor gibt, wird ein Kopierkonstruktor implizit als Standard deklariert.
Ich habe gerade einen schnellen Test auf gcc45 ausgeführt, und ein regulärer, nicht-variadischer Template-Konstruktor verhindert die Erstellung eines Compiler-generierten Standardkonstruktors. Mein Verdacht ist, dass sich die Regeln in C++ 0x geändert haben. –
@Dennis: Ich wäre _really_ überrascht, wenn C++ 0x Regeln ändern würde, die mit C++ 0x eingeführt werden. ':)' – sbi
@Dennis Also ist die verknüpfte Antwort gefälscht? Es besagt, dass "ein Vorlagenkonstruktor oder ein Zuweisungsoperator den vom Compiler erzeugten nicht unterdrücken wird". – fredoverflow