将int转换为size_t

abr*_*ert 4 c++ casting initializer-list

当我传递integer给一个时,我想知道clang编译器的以下警告std::initializer_list< size_t >:

non-constant-expression cannot be narrowed from type 'int' to 'unsigned long' in initializer list
Run Code Online (Sandbox Code Playgroud)

为什么可以int转换为a size_tint不能传递给a 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;
}    
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 8

来自[dcl.init.list]:

缩小转换是隐式转换[...] -从一个整数型或无作用域枚举类型到无法表示原始类型的不同之处,其中所述源是一个常量表达式积分优惠后,其值的所有值,整数类型将适合目标类型.

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

std::initializer_list<size_t> i_l = { i };
Run Code Online (Sandbox Code Playgroud)

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

s_t = i;
Run Code Online (Sandbox Code Playgroud)

这就是为什么第一行是格式错误但第二行不是.


Nat*_*ica 7

你和[dcl.init.list]/7发生了冲突

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

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

std::initializer_list<std::size_t> i_l = { 0 };
Run Code Online (Sandbox Code Playgroud)

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