clang和gcc中的这个警告似乎不正确

时间:2014-01-19 23:19:44

标签: c++ c++11 constructor initializer-list

我相信Bjarne Stroutrup的新书TCPL第4版第66页中的示例有一个小错误,因为class Vector_container没有std::initializer_list构造函数。错误消息here确认了这一点。

#include <iostream>

class Vector{
    double* elem;
    int sz;
public:
    Vector(int s):elem{new double[s]}, sz{s} { for(int i = 0; i != sz; ++i) elem[i]= 0; }
    Vector(std::initializer_list<double> lst): elem{new double[lst.size()]}, sz(lst.size()) { std::copy(lst.begin(), lst.end(), elem); }
    ~Vector() { delete[] elem; }
    double& operator[](int i) { return elem[i]; }
    int size() const { return sz; }
};

class Container{
public:
    virtual double& operator[](int i) = 0;
    virtual int size() const = 0;
    virtual ~Container() {}
};

class Vector_container:public Container{
    Vector v;
public:
    Vector_container(int s): v{s}{}
    ~Vector_container() {}
    double& operator[](int i) { return v[i]; }
    int size() const {return v.size(); }
};

void use(Container& c)
{
    const int sz = c.size();
    for(int i = 0; i != sz; i++) std::cout << c[i] << '\n';
}

int main()
{
    Vector_container vc{10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
    use(vc);
}

但是v{s}构造函数的成员初始化列表中为Vector_container(int)表达式发出的警告让我感到惊讶,因为它说:warning: narrowing conversion of 's' from 'int' to 'double' inside { },这似乎不正确,因为在这种情况下没有缩小。

此外,如果您将Vector_container vc{10, ..., 1};中的main()更改为Vector_container vc{10};,则错误消息会按预期消失,但警告会继续显示。尽管如此,编译器选择了std::initializer-list类的Vector构造函数,根据标准中的13.3.1.7/1,我认为这是正确的。

因此,我想知道是否有任何方法强制调用Vector(int)构造函数,而不是Vector类中的initializer-list ctor 。示例Vector_container vc{10};

1 个答案:

答案 0 :(得分:4)

你对重载决议是正确的:内部

Vector_container(int s): v{s}{}

初始化v{s}选择以下构造函数:

Vector(std::initializer_list<double> lst)

根据[over.match.list] / 1。

std::initializer_list<double>{s}创建s类型为int时,intdouble的转换范围正在缩小}(n3485)[dcl.init.list] / 7

  

缩小转化是隐式转化

     
      
  • [...]
  •   
  • 从整数类型或未范围的枚举类型到浮点类型,除非源是常量表达式,并且转换后的实际值将适合目标类型并且将   转换回原始类型时生成原始值,或
  •   
  • [...]
  •   

请注意,s此处不再是常量表达式(作为参数)。缩小转换可能不会出现在std::initializer_list对象的构造中,[dcl.init.list] / 5

  

如果缩小转换   需要初始化任何元素,程序格式不正确。

所以警告应该是一个错误(或者它是一个扩展名)。


  

因此,我想知道是否有办法强制调用Vector(int)构造函数,而不是Vector类中的初始化列表ctor。

我不确定我是否理解正确(请参阅对OP的评论),但不使用list-init解决问题:

Vector_container(int s): v(s) {}  // initializer-list ctor not viable