Search code examples
c++initializationlanguage-lawyerlist-initializationnarrowing

Narrowing from literal doesn't cause warning


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?


Solution

  • 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 ]