简体   繁体   English

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

[英]This warning in clang and gcc doesn't seem to be correct

I believe the example below in page 66 of Bjarne Stroutrup's new book, TCPL 4th edition, has a minor error, as the class Vector_container doesn't have an std::initializer_list constructor. 我相信Bjarne Stroutrup的新书TCPL第4版的第66页下面的例子有一个小错误,因为class Vector_container没有std::initializer_list构造函数。 The error message here confirms this. 这里的错误消息证实了这一点。

#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);
}

But the warning emitted for the expression v{s} in the member-initializer list for the Vector_container(int) constructor surprised me, as it says: warning: narrowing conversion of 's' from 'int' to 'double' inside { } , which doesn't seem to be correct, as there's no narrowing in this case. 但是对于Vector_container(int)构造函数的成员初始化列表中的表达式v{s}发出的警告让我感到惊讶,因为它说: warning: narrowing conversion of 's' from 'int' to 'double' inside { } ,这似乎不正确,因为在这种情况下没有缩小。

Also, if you change the expression Vector_container vc{10, ..., 1}; 另外,如果更改表达式Vector_container vc{10, ..., 1}; in main() to Vector_container vc{10}; main()Vector_container vc{10}; the error message disappears, as expected, but the warning continues to show off. 错误消息按预期消失,但警告继续显示。 Nonetheless the std::initializer-list constructor for the Vector class is chosen by the compiler, and I presume this to be correct, according to 13.3.1.7/1 in the Standard. 尽管如此,编译器选择了Vector类的std::initializer-list构造函数,根据标准中的13.3.1.7/1,我认为这是正确的。

Thus, I wonder if there's any way to impose the invoking of the Vector(int) constructor, instead of the initializer-list ctor in the Vector class, in this last example with Vector_container vc{10}; 因此,我想知道是否有任何方法Vector_container vc{10};最后一个示例中强制调用Vector(int)构造函数而不是 Vector中的initializer-list ctor Vector_container vc{10}; .

You're correct about the overload resolution: Inside 你对重载决议是正确的:内部

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

the initialization v{s} selects the following constructor: 初始化v{s}选择以下构造函数:

Vector(std::initializer_list<double> lst)

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

When the std::initializer_list<double> is created from {s} , where s is of type int , there is a narrowing conversion from int to double (n3485) [dcl.init.list]/7 当从{s}创建std::initializer_list<double> ,其中sint类型,从intdouble (n3485)[dcl.init.list] / 7有一个缩小的转换

A narrowing conversion is an implicit conversion 缩小转换是隐式转换

  • [...] [...]
  • from an integer type or unscoped enumeration type to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type, or 从整数类型或未范围的枚举类型到浮点类型,除非源是常量表达式,转换后的实际值将适合目标类型,并在转换回原始类型时生成原始值,或者
  • [...] [...]

Note that s here is not a constant expression any more (being a parameter). 请注意,此处的s不再是常量表达式(作为参数)。 Narrowing conversions may not appear in the construction of an std::initializer_list object, [dcl.init.list]/5 缩小转换可能不会出现在std::initializer_list对象的构造中,[dcl.init.list] / 5

If a narrowing conversion is required to initialize any of the elements, the program is ill-formed. 如果需要缩小转换来初始化任何元素,则程序格式不正确。

So that warning should be an error (or it's an extension). 所以警告应该是一个错误(或者它是一个扩展)。


Thus, I wonder if there's any way to impose the invoking of the Vector(int) constructor, instead of the initializer-list ctor in the Vector class. 因此,我想知道是否有任何方法强制调用Vector(int)构造函数,而不是Vector类中的initializer-list ctor。

I'm not sure if I understood you correctly (see comments to OP), but not using list-init here solves the problem: 我不确定我是否理解正确(请参阅对OP的评论),但不使用list-init解决了这个问题:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM