Sounds like the standard should say that it results in an implementation-defined value (or wording to that effect). Saying it's UB gives the compilers way too much leeway.
Great, now converting a float to int will cause the C compiler to randomly reformat your hard drive...
Hopefully this will be part of UB fixes for C++29, where plenty of UB is being redefined as erroneous behaviour instead.
> The correct fix is to bounds check before casting.
This will do wonders for speed. Actually explicitly using the safe isntr might be better. Something like this will happily compile to a single instr and cause you no grief even if the compiler had it out for you with UB. These instrs all clearly define outputs for all inputs (note that said outputs may not match across architectures)
static inline __attribute__((always_inline)) int f2i(float myFloat) {
int myInt;
#if defined(__arm__)
asm("VCVT.S32.F32 %0, %1":"=r"(myInt), "t"(myFloat));
#elif defined (__aarch64__)
asm("FCVTZS %0, %1":"=r"(myInt), "w"(myFloat));
#elif defined (__x86_64__)
asm("CVTTSS2SI %0, %1":"=r"(myInt), "x"(myFloat));
#else
#if 0 // be boring
if (myFloat <= TOO_SMALL_FLOAT || myFloat => TOO_BIG_FLOAT)
abort();
#else
#warning "Embrace the UB"
#endif
myInt = (int)myFloat;
#endif
return myInt;
}How could it be defined behaviour, when the result is different on ARM and x86?
The core guidelines library is definitely not doing the right thing here. Very odd.
float considered harmful
[dead]
Herb Sutter's comment on why it's ok is confusing to me:
> Regarding the use of UB internally: It's okay and if anyone is worried about it the use of UB is benign on the platforms we target (e.g., they don't involve hitting any hardware trap representations for these types)
Isn't the outcome of the UB (ie. whether it will "rm -rf /" or something else) dependent on both the target and the compiler? And the compiler (or future compiler) could plausibly make the assumption that the narrowing to an unrepresentable value will never occur and change behaviour because of it?