从c ++ 11开始,list initialization(包括aggregate initialization)不允许缩小转化率。所以基本上:
char c{1000}; // Does not compile with g++, clang, vc
可是:
std::pair<char, double> p{1000, 1.0};
与所有编译器一起编译?
可是:
std::pair<char, double> p{1000, {1.0}};
不用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}};
所以我的一个猜测可能是std::pair
有什么特别之处?还有什么能缩小支撑初始化的范围?
答案 0 :(得分: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 apparently doesn't consider the conversion needed to create a temporary for reference binding as part of the narrowing check。这可能是一个错误。pair
有一个template<class U1> pair(U1&&, const T2&)
构造函数模板,这是一个更好的匹配。使用此构造函数,第二个参数不会缩小,第一个参数是完全匹配,因此您不会收到任何错误或警告。