2010-11-24 14 views
23
struct A 
{ 
    A(const A& src); 
    A(const char* src); 
}; 
struct B 
{ 
    operator A(); 
    operator char*(); 
}; 
void test() 
{ 
    B v; 
    A s(v); 
} 

EDG/Comeau und MSVC ermöglicht den Code während GCC 4.4.4, CLANG und BCC es als mehrdeutig ablehnen.Sollte dies mehrdeutig sein oder nicht? (implizite Umwandlungen)

Ein C++ Ausschussmitglied antwortete mit dieser (zunächst):

Es ist nicht zweideutig; der Konstruktor A (const A &) ist besser als der Konstruktor A (const char *). Die const A & Parameter, der direkt auf das Ergebnis der Umwandlungsfunktion binden, so dass die Umwandlungsfolge zu betrachte Umwandlung eine vom Benutzer definiert werden, gefolgt von einer Identitäts Umwandlungs (13.3.3.1.4p1). Der const char * Parameter ist eine benutzerdefinierte Konvertierung gefolgt von einer Qualifikation Umwandlung, so ist es schlimmer.

Dann folgte er mit diesem.

Eigentlich lag ich falsch. Zwar ist es wahr, dass die zweite Umwandlung Sequenz in einer benutzerdefinierten Konvertierung Sequenz ein Tie-Break ist, mehr sucht eng an 13.3.3.2p3, die next-to-letzte Kugel zeigt, dass dieses Tie-Break gilt nur, wenn Die beiden Sequenzen enthalten dieselbe benutzerdefinierte Konvertierungssequenz und , was in diesem Beispiel nicht der Fall ist. Da eine Konstruktor der Umwandlung Sequenz B :: operator A() verwendet, und die andere Verwendungen b :: operator char *(), es gibt keine tiebreaker zwischen den beiden benutzerdefinierten Konvertierungssequenzen und sie sind zweideutig.

Meine Frage ist dies.

13.3.3.2 p3 stellt fest, dass,

zwei implizite Umwandlung Sequenzen von die gleiche Form gelten ununterscheidbar Konvertierungssequenzen sofern nicht eine der folgenden Regeln sind.

Von meinem Verständnis sind die Schlüsselwörter "eine der folgenden Regeln". Es bedeutet nicht, dass die Kugel, die "dieselbe Umwandlungssequenz" angibt, überschreibt alle oben genannten. Ich hätte gedacht "der Rang von S1 ist besser als der Rang von S2" wäre stattdessen anwendbar?

+12

Feiner Beweis, dass C++ es ein bisschen zu kompliziert ... – Hexagon

+0

Da Sie einen C++ Community-Mitglied Kontakt haben, sollten Sie ihn nicht einfach bitten, ein Problem zu stellen? (oder überprüfen Sie, ob es unter http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html abgelegt ist) –

+0

Ich habe nicht gesagt, dass es ein Problem gibt, ich versuche tatsächlich, das zu verstehen Standards. –

Antwort

4

Ja, das erwartete Ergebnis ist Mehrdeutigkeit zu den besten meiner Auslegung von Paragraf 13.3.3.2

Matching Argument ‚v‘ vom Typ ‚B‘ auf die Parameter entweder der überladenen Konstruktoren von ‚A‘ erfordert eine benutzerdefinierte Konvertierung Dort haben beide Sequenzen den CONVERSION-Rang.

Meine Interpretation ist, dass das folgende Zitat von $ 13.3.3.2 gilt

[...] Benutzerdefinierte Umwandlungsfolge U1 ist eine bessere Umwandlungsfolge als eine andere benutzerdefinierte Umwandlung Sequenz U2 wenn sie die gleiche benutzerdefinierte Umwandlungsfunktion oder Konstruktor und, wenn die zweite Standard Umwandlungsfolge von U1 enthalten ist, besser als die zweite Standardkonvertierung Sequenz von U2.

Beide rufen unterschiedliche Konvertierungsfunktionen in Klasse 'B' auf. Daher denke ich, dass die erste Bedingung selbst nicht erfüllt ist und daher das erwartete Ergebnis Ambiguität ist, da keine der Umwandlungssequenzen besser ist als die andere.

+0

Ja das ist eindeutig mehrdeutig, genau aus welchem ​​Grund du es erwähnst. Ich bin mir nicht sicher, warum das nicht akzeptiert ist swer. Es zeigt direkt, warum und warum es nicht eindeutig ist. Es ist jedoch falsch, dass es einen "Conversion" -Rang gibt. Wie Sie später sagen, haben Sie zwei benutzerdefinierte Konvertierungssequenzen. Ränge werden Standard-Konvertierungssequenzen (exakte Übereinstimmung, Promotion, Konvertierung) gegeben. Es gibt keine Vorstellung von einem Rang für eine benutzerdefinierte Konvertierungssequenz. –

1

Haftungsausschluss: Der Standard ist wirklich komplex auf diesen Teilen, so kann ich völlig falsch in meinem Verständnis sein.

Standarddefinition der besten lebensfähige Funktion (13.3.3):

diese Definitionen gegeben, eine tragfähige Funktion F1 definierte eine bessere Funktion als eine andere tragfähige Funktion F2, wenn für alle Argumente i, ICSI (F1) ist keine schlechte Umwandlungsfolge als ICSI (F2) und dann

[...]

  • der Kontext eine Initialisierung durch benutzerdefinierte Umwandlung (8,5 sehen, 012.13.3.1.5 und 13.3.1.6) und die Standardkonvertierungssequenz von dem Rückgabetyp F1 zum Ziel Typ (dh die Art der Entität initialisiert wird) ist eine bessere Umwandlungsfolge als der Standard Konvertierungssequenz von der Rückkehr Art von F2 zum Zieltyp.

Wenn ich richtig verstehe, die Art des Objekts aufgebaut ist, hat seine Bedeutung hier, und das wäre A::A(const A &) ein besserer Kandidat machen.


Johannes Siehe Kommentare zu sehen, warum diese Antwort falsch ist: Das ist in der Tat nicht eindeutig für die Ursache von Chubsdad hingewiesen.

+0

Definitiv relevant, +1, aber von den 2 genannten Kontexten, 13.3.1.5 betrifft nur die Initialisierung von Nicht-Klassen-Typen (wie "int") und 13.3.1.6 betrifft nur die Initialisierung von * Referenzen *. Also ich denke nicht, dass sie sich hier bewerben. –

+0

@j_random_hacker: ja aber 8.5 deckt die Initialisierung ab oder so ziemlich alles andere – icecrime

+0

@icecrime: Du hast recht, aber die Handlung verdichtet sich: Laut 8.5/12, 'A s (v);' ist * direct-initialization * - - Recht? Dann gilt die 6. Kugel von 8.5/14. Es ist zu groß, um hier zu zitieren, aber der entscheidende Punkt ist, dass es die Wörter "benutzerdefinierte Umwandlung" nicht erwähnt - * im Gegensatz zu den nächsten Fällen, in denen (einige) Kopierinitialisierungsfälle behandelt werden. Ich denke also nicht, dass der von Ihnen zitierte Ausschnitt hier gilt, und ich folge, dass "A s (v);" mehrdeutig ist, aber "A s = v;" sollte den "A (const A &)" ctor wählen. –

Verwandte Themen