Die unten mit clang35 -std=c++11
kompilieren fehlschlägt:List-Initialisierung und Überladungsauflösung von initializer_list Konstruktor fehlgeschlagen
#include <iostream>
#include <string>
#include <initializer_list>
class A
{
public:
A(int, bool) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
A(int, double) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
A(std::initializer_list<int>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
int main()
{
A a1 = {1, 1.0};
return 0;
}
mit Fehler
init.cpp:15:14: error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
A a1 = {1, 1.0};
^~~
init.cpp:15:14: note: insert an explicit cast to silence this issue
A a1 = {1, 1.0};
^~~
static_cast<int>()
OTOH, warnt es um die Verengung und kompiliert auf g++48 -std=c++11
init.cpp: In function ‘int main()’:
init.cpp:15:17: warning: narrowing conversion of ‘1.0e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
A a1 = {1, 1.0};
^
init.cpp:15:17: warning: narrowing conversion of ‘1.0e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
und erzeugt das Ergebnis
A::A(std::initializer_list<int>)
Sind beide Verhaltensweisen sinnvoll? Zitiert aus cppreference
All constructors that take std::initializer_list as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of type std::initializer_list
If the previous stage does not produce a match, all constructors of T participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all)
Da eingrenzende Konvertierungen sind nicht erlaubt, würde ich die Überladungsauflösung Schritt erwarten, dass die A(std::initializer_list<int>)
Konstruktor übereinstimmen und die stattdessen passen A(int, double)
ein. Zum Beispiel stellt sowohl mit clang35
und g++48
und Druck
A::A(int, double)
wie erwartet A(std::initializer_list<int>)
-A(std::initializer_list<std::string>)
ändern.
Vermutlich meinst du Clang 3.5. Was Sie die Binärdatei genannt haben, ist nicht wirklich hilfreich :) 'mv clang25 clang35'" oops " –
Sie haben Recht :) Dies ist die Versionskonvention, die vom Team verwendet wird, das Build-Systeme bei der Arbeit pflegt, und ich habe nie darüber nachgedacht. – Pradhan