A floating-point conversion, as the standard defines it, is a conversion between two floating-point types that isn't a promotion.
The simplest example is double
to float
:
double d = 0.1;
float f = d;
The standard says [conv.double]:
A prvalue of floating-point type can be converted to a prvalue of another floating-point type.
If the source value can be exactly represented in the destination type, the result of the conversion is that exact representation.
If the source value is between two adjacent destination values, the result of the conversion is an implementation-defined choice of either of those values.
Otherwise, the behavior is undefined.
The conversions allowed as floating-point promotions are excluded from the set of floating-point conversions.
In my example above, the source value cannot be exactly represented in the destination type. The value of d
is 0.10000000000000001
, whereas the value of f
is (likely) 0.10000000149011612
, and indeed if you cast f
back to a double
, is doesn't equal d
. However, this source value is between two adjacent destination values: f
and the previous representable float
value, 0.099999994039535522
. So the value of f
can be either of these values, but because 0.10000000149011612
is closer to 0.10000000000000001
than 0.099999994039535522
is, that's likely the value chosen by the implementation.
My question is about the last case:
Otherwise, the behavior is undefined.
Are there any values for which a conversion is undefined behavior? Since floating-point types have representations for +infinity and -infinity, I would assume there cannot be any source value that isn't exactly represented or between two adjacent destination values: any double
value is either an exact float
value (including NaN
) or between -infinity and +infinity, in which case it is between two adjacent float
values.
So what is the point of this "otherwise" case? Is it here to cover exotic types that are considered floating-point but aren't float
, double
, or long double
? Can a conversion between float
, double
, and long double
cause undefined behavior?
Nelfeal :
It turns out some floating-point implementations cannot represent infinities. MBF, as Eljay pointed out, is one of them. It's also implied by the existence of HUGE_VAL, which is the same as INFINITY if possible.\nHowever, this is extremely unlikely, and can be tested with std::numeric_limits<T>::has_infinity. Presumably, if this value is true, then there cannot be any undefined behavior with floating-point conversions.",
2022-11-15T21:20:38