将 int 转换为 size_t

Converting int to a size_t

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

non-constant-expression cannot be narrowed from type 'int' to 'unsigned long' in initializer list

为什么 int 可以转换为 size_tint 不能传递给 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;
}    

你 运行 与 [dcl.init.list]/7

有冲突

A narrowing conversion is an implicit conversion[...] from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.

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

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

那么即使 0 是一个 int 它也不会变窄,因为编译器知道 0 可以用每种类型表示。

来自[dcl.init.list]:

A narrowing conversion is an implicit conversion [...] — from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.

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

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

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

s_t = i;

这就是为什么第一行格式错误而第二行格式错误的原因。

当使用列表初始化来初始化对象时需要收缩转换时,程序格式错误。

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

8.5.4 List-initialization

...

3 List-initialization of an object or reference of type T is defined as follows:

...

— Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.

使用

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

属于同一条款。