我对以下c ++程序有疑问:
#include <vector>
#include <iostream>
int main(){
unsigned int i{5};
std::vector<double> v{i};
for(auto d : v){
std::cout << d << std::endl;
}
return 0;
}
g ++版本4.9.3和g ++版本5.4编译并生成警告:
test.cpp:6:25: warning: narrowing conversion of ‘i’ from ‘int’ to ‘double’ inside { } [-Wnarrowing]
std::vector<double> v{i};
我可以理解,根据规范,编译器想要使用std :: vector的初始化列表构造函数:
当非聚合类类型T的对象被列表初始化(8.5.4)时,重载决策分两个阶段选择构造函数:
- 最初,候选函数是类T的初始化列表构造函数(8.5.4),参数列表包含 初始化列表作为单个参数。
- 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数都是 类T的构造函数和参数列表由 初始化列表的元素。
但是我无法理解的是clang版本3.8无法编译程序,错误与上面的警告相同。我希望在这种情况下,初始化列表构造函数不可行(至少clang拒绝它),而应该使用std :: vector的“预期”构造函数。
我的问题:缩小转换是程序中的语法错误,因此(在我的理解中)应该使用std :: vector的构造函数来创建大小为5的std :: vector。那么为什么编译器忽略导致有效程序的构造函数?
提前谢谢!
答案 0 :(得分:1)
[dcl.init.list] / 3 否则,如果
T
是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载决策(13.3,13.3.1.7)选择最佳构造函数。如果转换任何参数需要缩小转换(见下文),则程序格式不正确。
缩小转换的必要性不会使构造函数不可行。相反,它通常会参与重载决策,然后,如果恰好选择了它,程序就会形成错误。