从c ++ 11开始,列表初始化(包括聚合初始化)不允许缩小转换.所以基本上:
char c{1000}; // Does not compile with g++, clang, vc
Run Code Online (Sandbox Code Playgroud)
但:
std::pair<char, double> p{1000, 1.0};
Run Code Online (Sandbox Code Playgroud)
编译所有编译器?
但:
std::pair<char, double> p{1000, {1.0}};
Run Code Online (Sandbox Code Playgroud)
不用VC编译(错误C2398),用clang发出警告并用g ++静默编译...
我本来期望VC行为无处不在,即一个非允许的缩小转换会引发错误.哪个是编译器是对的?
另一方面,以下代码段中的变量声明都没有编译:
struct X {
char c;
double d;
};
X x1{999, 1.0};
X x2{999, {1.0}};
struct Y {
char c;
double d;
Y (char c, double d) : c(c), d(d) { }
};
Y y1{999, 1.0};
Y y2{999, {1.0}};
Run Code Online (Sandbox Code Playgroud)
所以我的一个猜测可能是有一些特别的东西std::pair?还有什么东西可以缩小支撑初始化?
T.C*_*.C. 14
std::pair<char, double> p{1000, 1.0};未被诊断,因为它调用template<class U1, class U2> pair(U1&&, U2&&)构造函数(使用U1 == int和U2 == double),这是完全匹配; 在进入构造函数体之前,缩小不会发生.
std::pair<char, double> p{1000, {1.0}};无法调用该构造函数,因为braced-init-list {1.0}是非推导的上下文,因此您无法推断U2.
pair(const T1&, const T2&)构造函数; 但是clang显然不会考虑为缩小检查创建临时引用绑定所需的转换.这可能是一个错误.pair有一个template<class U1> pair(U1&&, const T2&)构造函数模板,这是一个更好的匹配.使用此构造函数,第二个参数不会缩小,并且第一个参数是完全匹配,因此您不会收到错误或警告.