将int转换为size_t

时间:2016-12-20 17:47:13

标签: c++ casting initializer-list

当我将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;
}    

3 个答案:

答案 0 :(得分:8)

来自[dcl.init.list]:

  

缩小转换是一种隐式转换[...] - 从整数类型或无范围枚举类型到整数类型,它不能代表原始类型的所有值,除非源代码是一个常量表达式,其积分促销后的值将适合目标类型。

我们正在将int(允许负值)转换为size_t(不允许),因此这是一个缩小的转化。缩小转换在列表初始化中是不正确的,这就是你在这里所做的:

std::initializer_list<size_t> i_l = { i };

然而,缩小转换率在其他地方也很好(就标准而言):

s_t = i;

这就是为什么第一行不良,但第二行不是。

答案 1 :(得分:7)

你违反了[dcl.init.list]/7

  

缩小转换是从整数类型或无范围枚举类型到整数类型的隐式转换,它不能表示原始类型的所有值,除非源是一个常量表达式,其值在积分之后促销将适合目标类型。

由于i不是常量表达式,因此这被视为缩小转换,并且初始化列表中不允许缩小转换。如果您要使用

std::initializer_list<std::size_t> i_l = { 0 };

即使0int,它也不会缩小,因为编译器知道0可以在每种类型中表示。

答案 2 :(得分:1)

当使用列表初始化初始化对象时需要缩小转换时,程序格式不正确。

从C ++ 11标准(强调我的):

  

8.5.4列表初始化

     

...

     

3对象或类型T的引用的列表初始化定义如下:

     

...

     

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

使用

int i = 0;
size_t s = {i};

属于同一条款。