2016-01-22 3 views
6

Versteckt diese Vorlage ctor ctr?Ist Vorlagenkonstruktor mit universellen Referenz ausblenden move construtor?

class A { 
    public: 
     template<typename T> 
     A(T &&t); 

     // move would be as this: 
     /* 
      A(A &&a); 
     */ 
}; 

Und wie in dieser Situation sollte ich dann move ctor implementieren? Sollte es mit der Standardsyntax A (A &&) oder einer Template-Spezialisierung sein?

+1

Es scheint, dass in gcc zumindest die templated ctor nicht berücksichtigt wird, wenn Sie umziehen: http://coliru.stacked-crooked.com/a/3c995d34b40fb4bc Wenn das der Fall ist nach dem Standard, dann können Sie move ctor in implementieren der übliche Weg. – user2079303

Antwort

3

Gemäß dem Standard (draft)

[class.copy]

3 A Nicht-Template Konstruktor für Klasse X ist eine Bewegung, wenn Konstruktor erste Parameter vom Typ X sind & &, const X & &, flüchtige X & & oder const volatile X & & und entweder gibt es keine weiteren Parameter oder auch alle anderen par Ameters haben Standardargumente (8.3.6). [Beispiel: Y :: Y (Y & &) ist ein Move-Konstruktor.

Nur Nicht-Vorlagenkonstruktoren können Move-Konstruktoren sein. Gleiches gilt für Kopierkonstruktoren . Daher wird der implizite Move-Konstruktor generiert.

Sie implementieren den Move-Konstruktor auf die übliche Weise. Die Spezialisierung funktioniert nicht, da der implizite Nicht-Template-Move-Konstruktor von der Überladungsauflösung bevorzugt wird.

Wenn der Argumenttyp nicht exakt mit const T& übereinstimmt, wird die Überladungsauflösung jedoch durch den Verweis auf die Vorlage erhalten. Dies kann leicht geschehen, wie in Praveens Beispiel zu sehen ist.

+1

** Gleiches gilt für Kopierkonstruktoren **. 'A a2 {a1};' ruft 'template' anstelle von' copy constructor' auf. Warum? http://ideone.com/JAfjLy – Praveen

+3

@Praveen weil 'a1' nicht' const' ist. Forwarding-Referenzen sind wirklich gierig. – TartanLlama

5

Die angenommene Antwort ist falsch. Während es wahr ist, dass template <typename T> A(T &&t) { } kein Move-Konstruktor ist, wussten Sie das bereits. Der Compiler wird eine Bewegung Konstruktor in diesem Fall und normale Überladungsauflösung wird implizit deklarieren wie erwartet:

A a{2}; // calls template 
A b = std::move(a); // calls move 
A c{a}; // calls template 

Es gibt nichts ausgeschlossen ist a von in c bewegt wird, auch wenn die Vorlage Konstruktor ist keine „move“ Konstrukteur.

+3

Woher wissen Sie, dass der Fragesteller weiß, dass die Vorlage nicht als Move-Konstruktor zählt? Wo heißt es in der akzeptierten Antwort, dass kein Bewegungskonstruktor implizit deklariert wird? (oder was ist "die angenommene Antwort ist falsch" _ beziehen sich auf?) – nwp