Betrachten Sie dieses Stück von C++ 11-Code:Eingrenzen Umwandlung in list-Initialisierung Bool - merkwürdiges Verhalten
#include <iostream>
struct X
{
X(bool arg) { std::cout << arg << '\n'; }
};
int main()
{
double d = 7.0;
X x{d};
}
Es gibt eine Verengung Umwandlung von einem Doppel zu einem bool in der Initialisierung von x
. Nach meinem Verständnis des Standards ist dies ein schlecht ausgearbeiteter Code und wir sollten etwas diagnostizieren.
Visual C++ 2013 gibt einen Fehler:
error C2398: Element '1': conversion from 'double' to 'bool' requires a narrowing conversion
jedoch beide Clang 3.5.0 und GCC 4.9.1, mit den folgenden Optionen
-Wall -Wextra -std=c++11 -pedantic
kompilieren diesen Code mit ohne Fehler und keine Warnungen. Das Ausführen des Programms gibt eine 1
(keine Überraschung dort).
Nun gehen wir tiefer in fremde Territorien.
ändern X(bool arg)
-X(int arg)
und plötzlich haben wir einen Fehler von Clang
error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
und eine Warnung bekam
warning: narrowing conversion of 'd' from 'double' to 'int' inside { } [-Wnarrowing]
Das sieht eher wie das, was ich erwartet hatte. Jetzt
, halten Sie den bool
Konstruktorargument (das heißt, zurückkehren zu X(bool arg)
) und double d = 7.0;
zu int d = 7;
ändern. Wiederum ein Engpass von Clang, aber GCC gibt überhaupt keine Diagnose aus und kompiliert den Code.
Es gibt ein paar mehr Verhaltensvarianten, die wir erhalten können, wenn wir die Konstante direkt an den Konstruktor übergeben, einige seltsam, einige erwartet, aber ich werde sie hier nicht auflisten - diese Frage wird zu lang wie es ist.
Ich würde sagen, dass dies einer der seltenen Fälle, wenn VC++ richtig und Clang und GCC sind falsch, wenn es um Standard-Konformität kommt, aber der jeweilige Track Records dieser Compiler gegeben, ich bin immer noch sehr zögerlich.
Was denken die Experten?
Standard-Referenzen (Zitate aus dem endgültigen Standard-Dokument für ++ 11 C, ISO/IEC 14882 bis 2011):
In 8.5.4 [dcl.init.list] Absatz 3, wir haben:
— Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.
im selben Abschnitt, in Ziffer 7 haben wir:
A narrowing conversion is an implicit conversion
— from a floating-point type to an integer type, or
— from long double to double or float, or from double to float, except where the source is a constant expression and the actual value after conversion is within the range of values that can be represented (even if it cannot be represented exactly), or
— from an integer type or unscoped enumeration type to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type, or
— from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type.
[ Note: As indicated above, such conversions are not allowed at the top level in list-initializations.—end note ]
in 3.9.1 [basic.grundlegende] Absatz 7, haben wir:
Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types.48 A synonym for integral type is integer type.
(ich alles in diesem Stadium zu hinterfragen begann ...)
Hey, wo hast alle Kommentare gehen? Einige von ihnen enthielten nützliche Informationen zur Diagnose des Problems, insbesondere für Clang. – bogdan
Einige dieser Kommentare wären sehr nützlich gewesen, um die Fehlerberichte zu archivieren, ich verstehe nicht, warum sie alle gelöscht wurden, vielleicht kann die Frage auf [meta] (http://meta.stackoverflow.com/) helfen, das tue ich nicht Hab jetzt keine Zeit. Sie könnten auch eine benutzerdefinierte Flagge ausprobieren, aber Sie wissen nicht, wie lange Sie noch arbeiten werden. –
@dyp nicht sicher, dass Sie dies sehen werden, da Ihr Kommentar gelöscht wurde, aber Ihre nützlichen Links zum Quellcode des Klangs entfernt wurden und es hilfreich wäre, sie wieder zu haben. –