Was ist das vermeintliche Verhalten der Copy-List-Initialisierung bei einem Initialisierer mit einem Konvertierungsoperator?

8
%Vor%

Der obige Code kompiliert auf g ++ und vc ++, aber nicht auf clang ++.
Die traditionelle Syntax AAA a = b; kompiliert ok für alle drei.

%Vor%

Der obige Code kompiliert nicht in g ++, vc ++, clang ++. Der einzige Unterschied gegenüber dem ersten Codeausschnitt besteht darin, dass ich die beiden vom Benutzer bereitgestellten Konstruktoren von AAA entfernt habe.
Auch hier wird die traditionelle Syntax AAA a = b; auf allen dreien korrekt kompiliert.

Ich bin mir ziemlich sicher, dass die traditionelle Syntax der Kopierinitialisierung im Falle eines Initialisierers mit einem Konvertierungsoperator wohldefiniert ist. Aber für die C ++ 11 Kopierlisten-Initialisierung bin ich verwirrt. Ist clang die richtige Aktion, die die Initialisierung ablehnt oder g ++ / vc ++ die korrekte Aktion übernimmt und die Initialisierung akzeptiert (wie im ersten Code-Snippet zu sehen ist)? Und warum wird eine so geringfügige Änderung wie im zweiten Codeausschnitt zu einem signifikant anderen Verhalten führen? Was ist der Unterschied zwischen Copy-List-Initialisierung und traditioneller Copy-Initialisierung in diesem Fall immerhin?

EDIT: Hinzufügen eines dritten Falles:

%Vor%

Der obige Code wird für alle drei Compiler kompiliert. Der Konvertierungsoperator funktioniert, wenn der endgültige Zielkonstruktor nicht der Kopierkonstruktor ist?
In diesem Fall kann die traditionelle Syntax AAA a = b; nicht wie erwartet für alle drei Kompilierungen kompiliert werden, da die traditionelle Kopi-Initialisierung höchstens eine Ebene der benutzerdefinierten impliziten Konvertierung vor dem endgültigen Konstruktor erlaubt (das endgültige Ziel kann nur der Kopierkonstruktor).

Bitten um eine systematische Erklärung für all diese Unordnung ...

    
goodbyeera 17.02.2014, 12:54
quelle

1 Antwort

5

Zum ersten Mal treffen Sie Ссылка (siehe letzter Testfall): Wenn die Initialisierung der Liste nur ein einzelnes Element an einen Copy / Move-Konstruktor einer Klasse X übergibt, sind benutzerdefinierte Konvertierungen für dieses einzelne Element nicht erlaubt, um es in den Parameter X zu konvertieren. Siehe auch Ссылка , mit dem Clang diese Regel implementiert hat

Für die Sekunde: Sie schlagen Ссылка (aber stattdessen Wenn Sie ein Objekt desselben Typs verwenden, verwenden Sie ein Objekt eines nicht verwandten Typs. Ihr Aggregat stellt einfach kein Datenelement vom Typ BBB bereit.

Für die dritte: Keine der beiden obigen Situationen trifft zu, also funktioniert die Listeninitialisierung und ruft den CCC -Konstruktor von AAA auf. Die = b -Initialisierung schlägt fehl, da nur versucht werden kann, die b in eine einzelne benutzerdefinierte Konvertierungssequenz in AAA zu konvertieren. Aber hier müssten Sie zuerst in CCC und dann wieder in AAA konvertieren. Bei der Initialisierung der Liste besteht diese Einschränkung, dass nur eine benutzerdefinierte Konvertierung durchgeführt wird, nicht.

    
Johannes Schaub - litb 17.02.2014, 15:04
quelle

Tags und Links