List initialization (the {...}
syntax) doesn't allow narrowing conversions. For example, trying to list-initialize an int i
with 3.14f
holds a compilation error, as conversion from floating point values to integers is narrowing:
<source>:11:32: error: narrowing conversion of '3.1400001e+0f' from 'float' to 'int' inside { } [-Wnarrowing]
int i{3.14f};
^
With that said, why is it possible to construct a float f
with 3.14
, which is of type double
? (Conversion from double
to float
is considered a narrowing one.) Doing the following:
float f{3.14};
Holds no compilation errors.
In the list of what is considered a narrowing conversion, constant expressions that fit within the target type are an exception. So while in general double to float is narrowing, when your double is actually a literal this is permitted.
http://coliru.stacked-crooked.com/a/6949f04fa4a8df17
From the draft I have on hand (I think close to C++14):
8.5.4 List-initialization
(7.2) A narrowing conversion is an implicit conversion...
...from long double to double or float, or from double to float, except where the source is a constant expression and the actual value after conversion is within the range of values that can be represented (even if it cannot be represented exactly),