int a = 0; short b{a}; short c{0};
The compiler gives a waring for short b{a}
. I can understand this, because int
is narrowed to short
.
However, it doesn't give a warning to short c{0}
, which is weird to me. My remember for literal integers, the type of 0
should at least be int
. So narrowing from int
to short
is happening here. Why doesn't the compiler give a warning?
For short c{0};
, narrowing conversion doesn't occur. Because 0
is a constant expression and can be stored exactly in a short
.
(emphasis mine)
list-initialization limits the allowed implicit conversions by prohibiting the following:
...
conversion from integer or unscoped enumeration type to integer type that cannot represent all values of the original, except where source is a constant expression whose value can be stored exactly in the target type
Relevant explanations and examples from the standard, $8.6.4/7 List-initialization [dcl.init.list]:
(emphasis mine)
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.
[ Note: As indicated above, such conversions are not allowed at the top level in list-initializations. — end note ] [ Example:
// ... const int z = 99; // ... char c4{z}; // OK: no narrowing needed unsigned char uc1 = {5}; // OK: no narrowing needed // ... float f2 { 7 }; // OK: 7 can be exactly represented as a float // ...
— end example ]