为什么std :: vector <double> v {unsigned int}没有选择有效的构造函数?

时间:2018-03-22 15:32:53

标签: c++11 compilation

我对以下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。那么为什么编译器忽略导致有效程序的构造函数?

提前谢谢!

1 个答案:

答案 0 :(得分:1)

  

[dcl.init.list] / 3 否则,如果T是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载决策(13.3,13.3.1.7)选择最佳构造函数。如果转换任何参数需要缩小转换(见下文),则程序格式不正确。

缩小转换的必要性不会使构造函数不可行。相反,它通常会参与重载决策,然后,如果恰好选择了它,程序就会形成错误。