在初始化列表的上下文中缩小的奇怪行为
Strange behavior of narrowing in context of initializer lists
有人知道为什么编译时没有警告
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
引用与您的 相同的部分,[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.
什么算常量表达式?在 [expr.const]:
中定义
A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions: [...]
— an invocation of a function other than a constexpr
constructor for a literal class, a constexpr
function, or an implicit invocation of a trivial destructor
— [...]
— an lvalue-to-rvalue conversion (4.1) unless it is applied to a non-volatile
glvalue of integral or enumeration type that refers to a complete non-volatile
const
object with a preceding initialization, initialized with a constant expression
— [...]
所以,i
是const int i = 1024;
中的一个常量表达式,因为i
是一个非volatile
const
整型对象,用常量初始化表达式(1024
)。但在第二个示例中,pow()
不是常量表达式,因为它是对非 constexpr
函数的调用。
因此,第一个示例不算缩小范围,但第二个示例算作缩小范围。您可以将其视为编译器 知道 1024 可以,但不知道 pow(2, 10) 可以。
有人知道为什么编译时没有警告
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
引用与您的
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.
什么算常量表达式?在 [expr.const]:
中定义A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions: [...]
— an invocation of a function other than aconstexpr
constructor for a literal class, aconstexpr
function, or an implicit invocation of a trivial destructor
— [...]
— an lvalue-to-rvalue conversion (4.1) unless it is applied to a non-volatile
glvalue of integral or enumeration type that refers to a complete non-volatile
const
object with a preceding initialization, initialized with a constant expression
— [...]
所以,i
是const int i = 1024;
中的一个常量表达式,因为i
是一个非volatile
const
整型对象,用常量初始化表达式(1024
)。但在第二个示例中,pow()
不是常量表达式,因为它是对非 constexpr
函数的调用。
因此,第一个示例不算缩小范围,但第二个示例算作缩小范围。您可以将其视为编译器 知道 1024 可以,但不知道 pow(2, 10) 可以。