当我将integer
传递给std::initializer_list< size_t >
时,我想知道clang编译器的以下警告:
non-constant-expression cannot be narrowed from type 'int' to 'unsigned long' in initializer list
为什么int
可以投放到size_t
,但int
不能传递给std::initializer_list< size_t >
,即
int main()
{
size_t s_t = 0;
int i = 0;
std::initializer_list<size_t> i_l = { i }; // warning
s_t = i; // no warning
return 0;
}
答案 0 :(得分:8)
来自[dcl.init.list]:
缩小转换是一种隐式转换[...] - 从整数类型或无范围枚举类型到整数类型,它不能代表原始类型的所有值,除非源代码是一个常量表达式,其积分促销后的值将适合目标类型。
我们正在将int
(允许负值)转换为size_t
(不允许),因此这是一个缩小的转化。缩小转换在列表初始化中是不正确的,这就是你在这里所做的:
std::initializer_list<size_t> i_l = { i };
然而,缩小转换率在其他地方也很好(就标准而言):
s_t = i;
这就是为什么第一行不良,但第二行不是。
答案 1 :(得分:7)
缩小转换是从整数类型或无范围枚举类型到整数类型的隐式转换,它不能表示原始类型的所有值,除非源是一个常量表达式,其值在积分之后促销将适合目标类型。
由于i
不是常量表达式,因此这被视为缩小转换,并且初始化列表中不允许缩小转换。如果您要使用
std::initializer_list<std::size_t> i_l = { 0 };
即使0
是int
,它也不会缩小,因为编译器知道0
可以在每种类型中表示。
答案 2 :(得分:1)
当使用列表初始化初始化对象时需要缩小转换时,程序格式不正确。
从C ++ 11标准(强调我的):
8.5.4列表初始化
...
3对象或类型T的引用的列表初始化定义如下:
...
- 否则,如果
T
是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载决策(13.3,13.3.1.7)选择最佳构造函数。 如果转换任何参数需要缩小转换(见下文),则程序格式不正确。
使用
int i = 0;
size_t s = {i};
属于同一条款。