5

有人知道为什么编译时没有警告吗

int main()
{
  const int i = 1024;
  std::initializer_list<size_t> i_l = { i }; // no warning

  return 0;
}

但不

int main()
{
  const int i = pow(2,10);
  std::initializer_list<size_t> i_l = { i }; // warning

  return 0;
}

警告:

non-constant-expression cannot be narrowed from type 'int' to 'unsigned long' in initializer list [-Wc++11-narrowing]
      std::initializer_list<size_t> i_l = { i }; i_l = i_l; // warning
4

1 回答 1

4

引用与上一个问题[dcl.init.list]相同的部分:

缩小转换是一种隐式转换 [...] — 从整数类型或无作用域枚举类型到不能表示原始类型的所有值的整数类型,除非源是常量表达式,其值在整数提升后将适合目标类型

什么算作常量表达式?这在 [expr.const] 中定义:

条件表达式 e 是一个核心常量表达式,除非根据抽象机 (1.9) 的规则对 e 的求值将求值以下表达式之一: [...]
— 调用非constexpr构造函数的函数对于文字类、constexpr函数或普通析构函数的隐式调用
- [...]
- 左值到右值转换 (4.1),除非它应用于volatile指向的整数或枚举类型的非左值一个完整的非volatile const对象,前面有初始化,用一个常量表达式初始化
- [...]

所以,i是一个常量表达式,const int i = 1024;因为i是一个用常量表达式 ( )volatile const初始化的非整型对象。1024但在第二个例子中,pow()is 不是一个常量表达式,因为它是一个非constexpr函数的调用。

因此,第一个示例不算缩小,但第二个示例可以。你可以把它想象成编译器知道1024 没问题,但不知道 pow(2, 10) 是。

于 2016-12-21T01:07:50.210 回答