Auflösung von Mehrdeutigkeiten
-
Hi,
ich habe folgendes Problem hier: Ein QString (von QT, Implementation interessiert nicht weiter) soll in einen std::string umgewandelt werden. Der Code der das macht sieht so aus:
void func( const QString& q) { std::string s = q; }Der KAI-Compiler frisst das auch (warum auch immer). Der GNU meckert allerdings (meiner Meinung nach zu Recht), dass er das nicht auflösen kann. Denn:
class QString { ... operator char* (); operator std::string (); }und der Konstruktor von std::string kann beides annehmen.
Meine Frage daher: Gibt es irgendeine Regel, nach der ein Konstruktor bevorzugt werden sollte? Oder ist der Fehler vom GNU richtig, dass es so nicht aufgelöst werden kann?
Einer der beiden Compiler macht anscheinend etwas falsch und es geht nun darum, ob der Code angepasst werden muss oder nicht (ist natürlich nicht nur diese 1 beispielhafte Stelle, sondern über ne Menge Module verstreut).Das hier schluckt übrigens auch der GNU...
std::string func( const QString& q) { return q; }Ich vermute mal, dass er hier über den Return-Typ entscheidet, welchen Cast-Operator er verwenden soll.
Bitte keine Vorschläge á la "gleich operator std::string hinschreiben" (denn das wäre dann die Anpassungsarbeit die anfällt). Es geht mir dadrum, ob es eine Regel im Standard gibt oder nicht.
Noch eine Anmerkung:
Die STL die dem KAI und dem GNU beiliegt, implementieren beide string als basic_string<char>.
-
Was sagt denn der Comeau Online Compiler dazu?
-
:o schrieb:
Was sagt denn der Comeau Online Compiler dazu?
Ich habe 5 Minuten lang aufmerksam mein Ohr an den Monitor gelegt, habe aber nicht gehört, dass der Comeau etwas gesagt hat.
Und beantworten tut es meine eigentliche Frage nicht. Compilieren tut es der Comeau - und er benutzt den operator std::string() (operator std::string private machen gibt nen Compile-Fehler).
Nochmal die Frage: Warum ist das so? Macht der Comeau es denn richtig? Wie lautet die Regel, nach der gewählt wird?
Den Code hier hab ich zum Testen durch den Comeau gejagt:
#include <string> class qstr { public: operator char*() const { return 0; } operator std::string() const { return std::string(); } }; void f( const qstr& q) { std::string s( q); }
-
@7H3 N4C3R
Das der Comeau deinen Beispielcode übersetzt ist klar. Du hast zwei mögliche Konverierungen. Einmal nach char* und einmal nach std::string. std::string kann u.A. mit einen const char* und einem std::string erzeugt werden. D.h. die erste Version benötigt eine cv-Conversion. Die zweie Version ist ein exact match, welche nach C++ Auflösungsregeln bevorzugt wird.Ändern wir nun:
class qstr { public: operator char*() const { return 0; } operator std::string() const { return std::string(); } };in
class qstr { public: operator const char*() const { return 0; } operator std::string() const { return std::string(); } };dann ist
std::string s(q);mehrdeutig, da beide Konvertierungen ein exact match sind.
Schreibst du hingegen:
std::string s = q;dann machst du aus der "direct intialization" eine "copy-initialization" (siehe 8.5 und http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=copyvsdirect#Answ)
Bei der Copy-Initialisierung eines Typs T mit einem Objekt vom Typ S werden von S nur die Konvertierungsoperatoren berücksichtigt (laut 13.3.1.4), die ein T liefern. Demzufolge wird von q nur der op std::string berücksichtigt.
Du hast also nur eine mögliche Konvertierung und damit natürlich keine Mehrdeutigkeit.
-
Ups, ich meinte natürlich const char*. Und stimmt, dann haut es mir auch der Comeau um die Ohren.
Die Regel mit der Copy-Initialization kannte ich allerdings noch nicht - ist aber gut zu wissen. Ansonsten wäre der QT-Code an der Stelle auch irgendwie schwachsinnig

Dankeschön!
-
Nun ist es amtlich: c++.de'ler wissen früher bescheid

-
Japps das stimmt! 
Ich war jung und ich brauchte die Lösung
