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

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

本文关键字:警告 不正确 gcc clang      更新时间:2023-10-16

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

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

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

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

因此,我想知道是否有任何方法可以强制调用Vector(int)构造函数,而不是Vector类中的初始值设定项列表ctor,在最后一个例子中使用Vector_container vc{10};

您对过载分辨率的看法是正确的:在内部

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

初始化CCD_ 14选择以下构造函数:

Vector(std::initializer_list<double> lst)

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

当从{s}创建std::initializer_list<double>时,其中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