在初始化列表的上下文中缩小的奇怪行为

abr*_*ert 5 c++ initializer-list narrowing

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

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

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

但不

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

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

警告:

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
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 4

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

\n\n
\n

缩小转换是从整数类型或无作用域枚举类型到不能表示原始类型的所有值的整数类型的隐式转换 [...] \xe2\x80\x94 ,除非源是常量表达式,其积分促销后的价值将符合目标类型

\n
\n\n

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

\n\n
\n

条件表达式 e 是核心常量表达式,除非对 e 的求值遵循抽象机 (1.9) 的规则,将求值以下表达式之一: [...]
\n \xe2\x80\x94 调用constexpr文字类的构造函数以外的函数、constexpr函数或简单析构函数的隐式调用
\n \xe2\x80\x94 [...]
\n \xe2\x80\x94 左值到右值转换 (4.1) 除非它应用于volatile整数或枚举类型的非泛左值,该类型引用具有volatile const先前初始化的完整非对象,并使用常量表达式初始化
\n \xe2\x80\x94 [...]

\n
\n\n

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

\n\n

因此,第一个示例不算作缩小,但第二个示例算作缩小。您可以将其视为编译器知道1024 可以,但不知道 pow(2, 10) 可以。

\n

  • @Ap31 格式错误需要诊断,但标准不要求该诊断的含义。为此,有“-Werror”。 (2认同)