Kar*_*lte 10 c++ visual-studio c++11
我在Visual Studio上测试了以下代码,它编译并打印"A(double)".
#include <iostream>
#include <initializer_list>
struct A {
A(std::initializer_list<int>) { puts("initializer_list<int>"); } // (1)
A(std::initializer_list<float>) { puts("initializer_list<float>"); } // (2)
A(double) { puts("A(double)"); } // (3)
};
int main() {
A var{ 1.1 };
}
Run Code Online (Sandbox Code Playgroud)
但是,IntelliSense和http://ideone.com/ZS1Mcm都不同意,他们说构造函数"A :: A"的多个实例与参数列表匹配(意味着两个初始化列表构造函数).请注意,如果删除了(1)或(2),则代码不再编译,因为"从'double'转换为'float'需要缩小转换".
这是一个错误吗?行为感觉不一致,但我在VS13和VS15中看到了相同的行为,所以可能还有更多呢?
该代码格式不正确。\xc2\xa78.5.4/(3.6) 适用:
\n\n\n\n\n否则,如果
\nT是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载决策选择最好的构造函数(13.3、13.3.1.7)。
现在,\xc2\xa713.3.3.1.5 开始
\n\n\n\n\n当参数是初始值设定项列表 (8.5.4) 时,它不是表达式,并且应用特殊规则将其转换为参数类型。[\xe2\x80\xa6]\n 如果参数类型为
\nstd::initializer_list<X>且初始化器列表的所有\n 元素都可以隐式转换为X,\n 隐式转换序列是转换\n 的元素所需的最差转换list 到X,或者如果初始值设定项列表没有\n 元素,则进行恒等转换。
Converting1.1的类型为double(!), toint是具有转换等级的浮点积分转换,而 from 1.1to的转换float是浮点转换 - 也具有转换等级。
因此,这两种转换同样好,并且由于 \xc2\xa713.3.3.2/(3.1) 也无法区分它们,因此调用是不明确的。请注意,在重载决策完成之前,缩小范围不会发挥作用,因此不会影响候选集或选择过程。更准确地说,候选人必须满足 13.3.2/3 中规定的要求:
\n\n\n\n\n其次,为了
\nF成为一个可行的函数,每个参数都应存在一个隐式转换序列(13.3.3.1),该序列将该参数转换为 的相应参数F。
然而,如第二个引用所示,转换{1.1}为 的隐式转换序列是从到 的std::initializer_list<int>最差转换,这是一种浮点积分转换 - 并且是一个有效的(并且现有的!)转换。1.1int
{1.1f}或更改initializer_list<float>to <double>,则代码格式良好,因为转换1.1f为float是身份转换。标准在(3.6)中给出了相应的例子:\n\n\n\n\n[例子:
\n\nRun Code Online (Sandbox Code Playgroud)\n\nstruct S {\n S(std::initializer_list<double>); // #1\n S(std::initializer_list<int>); // #2\n\n};\nS s1 = { 1.0, 2.0, 3.0 }; // invoke #1\n\xe2\x80\x94结束示例]
\n
更有趣的是,
\n\nstruct S {\n S(std::initializer_list<double>); // #1\n S(std::initializer_list<int>); // #2\n\n};\nS s1 = { 1.f }; // invoke #1 \nRun Code Online (Sandbox Code Playgroud)\n\n也是有效的1.f- 因为从到 的转换double是浮点促销,具有促销排名,这比转换排名更好。
| 归档时间: |
|
| 查看次数: |
487 次 |
| 最近记录: |