Why does list initialization allow conversion from double to float values?
Asked Answered
J

1

11

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.

Jimmyjimsonweed answered 7/1, 2018 at 20:20 Comment(1)
Are you sure that conversions from double to float are allowed? extern double y; struct X { float f; } x{y}; errors out for me.Vmail
S
13

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),

Serotherapy answered 7/1, 2018 at 20:24 Comment(9)
Same thing when initializing char with int value.Moreno
Wow why is pi_const (in the linked code) not considered a constant expression? Or is that a question outside of this one's scope?Donatist
@MárioFeroldi: It is considered a constant expression. :) pi, however, is not.Serotherapy
@Serotherapy completely overlooked it! I'm deleting these comments in a few moments.Donatist
@MárioFeroldi Leave them here for other people who might have had the same thought process. They still add value.Villanelle
@MárioFeroldi Clarified the example a bit.Serotherapy
Wow, so losing precision is allowed. 3.14 is an infinite binary fraction, so (float) 3.14 != 3.14.Wirth
@ArneVogel: Yeah. You could imagine there was a separate kind of conversion error for floating-point values that don't fit in their destination - if such a thing existed, then it might make sense for this narrowing conversion rule to simply reference that rule. However, that rule doesn't exist and practically most developers don't actually care if their literal is exactly represented; I believe this is the motivation for this exception to the rule.Serotherapy
And, equally, 4.14 can't be perfectly represented in double either, I think.I'm not sure what the criteria for float fit are, though. Is it purely exponent range or would too many digits be considered unacceptable? eg 1.23456789 would have clearly truncated precision in float.Dishwasher

© 2022 - 2024 — McMap. All rights reserved.