Überladene Bool / String Ambiguität

9

Warum wirft C ++ das String-Literal, das ich als Bool anstelle von String übergebe?

%Vor%

Ausgabe: 1

Liegt es daran, dass der Compiler nicht intelligent genug ist, um den Sprung von char * nach string zu machen, sondern nur davon ausgeht, dass bool einem Zeiger am nächsten kommt? Ist meine einzige Option, einen expliziten char * -Konstruktor zu erstellen, der genau das Gleiche wie der Zeichenkettenkonstruktor tut?

    
RPGillespie 16.10.2014, 21:11
quelle

4 Antworten

13

Wenn Sie C ++ 11 haben, können Sie einen delegierenden Konstruktor verwenden:

%Vor%

Der Grund dafür, dass der boolesche Konvertierungskonstruktor gegenüber dem von std::string gewählt wurde, liegt darin, dass die Konvertierung von char const* nach bool eine Standardkonvertierung ist, während die von std::string eine benutzerdefinierte Konvertierung ist. Standard-Conversions haben einen höheren Rang als benutzerdefinierte Conversions.

    
0x499602D2 16.10.2014, 21:51
quelle
3

Mit

%Vor%

es wird das erwartete Ergebnis geben.

Warum ist das so?

Es liegt an den Standardkonvertierungen:

  • "Hallo" wird als const char* Zeiger
  • verstanden
  • Dieser Zeiger kann in ein bool konvertiert werden (Abschnitt 4.12 des Standards: "Ein prvalue von (...) pointer (...) type kann in einen prvalue vom Typ bool konvertiert werden." )
  • Die Konvertierung von "hallo" in string wird nicht berücksichtigt, da in Abschnitt 12.3 des Standards erklärt wird, dass " Typkonvertierungen von Klassenobjekten durch Konstruktoren und Konvertierungsfunktionen angegeben werden können. Diese Konvertierungen werden als benutzerdefinierte Konvertierungen bezeichnet "und" Benutzerdefinierte Konvertierungen werden nur dort angewendet, wo sie eindeutig sind ". Hätten Sie nicht den bool -Konstruktor, würde die std::string -Konvertierung implizit erfolgen.

Wie erhalten Sie, was Sie erwartet haben?

Fügen Sie einfach den fehlenden Konstruktor für String-Literale hinzu:

%Vor%

Statt einen Konstruktor von Grund auf neu zu schreiben, können Sie natürlich auch einen Delegaten wählen, wie von 0x499602D2 in einer anderen Antwort vorgeschlagen.

    
Christophe 16.10.2014 21:25
quelle
2

Wenn Sie eine überladene Methode auswählen, ist dies die Reihenfolge, die der Compiler versucht:

  1. Genaue Übereinstimmung
  2. Werbung
  3. Standard numerische Umwandlung
  4. Benutzerdefinierte Operatoren

Ein Zeiger wird nicht auf bool hochgestuft, aber er konvertiert in bool . A char* verwendet einen Operator std , um in std::string zu konvertieren. Beachten Sie, dass wenn char* die gleiche Zahl in dieser Liste verwendet, um in beide bool und std::string zu konvertieren, wäre es mehrdeutig, welche Methode der Compiler wählen sollte Überlast "Fehler.

Ich würde mein Gewicht hinter die Lösung von 0x499602D2 werfen. Wenn Sie C ++ 11 haben, rufen Sie am besten an: A(char* s) : A(std::string(s)){} Wenn Sie C ++ 11 nicht haben, dann würde ich einen A(char* s) -Konstruktor erstellen und die Logik des A(std::string) -Konstruktors in eine Methode abstrahieren und diese Methode von beiden Konstruktoren aufrufen.

Ссылка

    
Jonathan Mee 16.10.2014 22:29
quelle
2

Vor kurzem habe ich dieses Problem auch, lassen Sie mich einen anderen Weg teilen.

Sie können den bool -Konstruktor in ein unsigned char ändern. Also die Verfall und implizite Konvertierung von String-Literal nicht passieren, und der std::string -Konstruktor findet statt.

%Vor%

Auf diese Weise müssen Sie nicht immer Überladungen für std::string und const char* bereitstellen, wodurch der Code aufgebläht wird, der std::string am Clientaufrufstandort erstellt.

Ich behaupte nicht, dass es besser ist, aber es ist einfacher.

    
Nico Engels 16.08.2016 17:07
quelle