8

Ich testete den folgenden Code mit 3 Compilern und bekam 3 verschiedene Ergebnisse: Fehler, Warnung und ok.Umwandlung von nullptr_t nach bool: gültig oder nicht?

  • GCC (5.3): Fehler: ungültige benutzerdefinierte Konvertierung von 'std :: nullptr_t' to 'const Sache &'
  • Clang (3.8): Warnung: implizite Umwandlung von nullptr konstant boolsche
  • MSVC (14.1): kein Fehler, keine Warnung

Welche Compiler ist richtig? Ich weiß, es ist eine triviale Umwandlung zwischen einem Zeigertyp und bool. Aber was ist mit std::nullptr_t und bool?

(Am Ende Clang und MSVC sind beide mit dem Code in Ordnung. Clang etwas ausführlicher in einer positiven Art und Weise ist.)

struct Thing 
{ 
    Thing(bool) {} 
}; 

void addThing(const Thing&){} 

int main() 
{ 
    addThing(nullptr); // warning or error on this line 
} 

Antwort

8

Dies ist ungültig. Nach der Regel von boolean conversions:

A prvalue of type std::nullptr_t , including nullptr , can be converted to a prvalue of type bool in context of direct-initialization. The resulting value is false .

Zitate aus dem Standard, §7.14/1 Boolean conversions [conv.bool]

For direct-initialization, a prvalue of type std​::​nullptr_­t can be converted to a prvalue of type bool ; the resulting value is false .

Die Umwandlung nur für direct-initialization erlaubt, aber nicht copy-intialization, die für das Bestehen Argument an eine Funktion, den Fall unter anderem durch Wert. z.B.

bool b1 = nullptr; // invalid 
bool b2 {nullptr}; // valid 

Also GCC ist korrekt. Aber Clang ist auch nicht falsch; Der Standard erfordert nur, dass der Compiler eine Diagnose ausgibt, wenn das Programm schlecht formatiert ist, also muss er Ihnen sagen, dass etwas passiert, danach könnte es alles tun.

Siehe Does the C++ standard specify that for some cases the compiling should fail with an error?

+0

Bin ich der einzige hier durch die logische Inkonsistenz gestört ein? (nicht die Antwort selbst). Ich bin mir sicher, dass es aus anderen Gründen durchgesetzt wurde, aber das scheint mir wirklich ein Fall zu sein, in dem keiner in Abwesenheit eines '_cast'-Betreibers arbeiten sollte. –

+1

@BrettHale Meine Interpretation ist, dass 'nullptr' nur implizit in Null-Zeiger (von jedem Zeigertyp und jedem Zeiger auf Elementtyp) konvertiert werden kann. Die Umwandlung in 'bool' muss explizit sein, aber trotzdem erlaubt (aus Gründen der Konsistenz anderer Zeiger?). – songyuanyao

+1

@Brett Hale Ich sehe es nicht als inkonsistent. Wenn man einen Konstruktor explizit aufruft, überraschen Überraschungen, ruft er Konstruktoren auf, die explizit markiert wurden, was genau einer der Dinge ist, die der statische Cast tun wird! Das sind primitive Typen, also haben sie nicht buchstäblich Konstruktoren, aber die Idee ist dieselbe. –

Verwandte Themen