I wanted to test the behavior of floats near infinity. For that I naively wrote the following code:
#include <limits>
#include <iostream>
int main() {
constexpr float foo = std::numeric_limits<float>::infinity() - std::numeric_limits<float>::epsilon();
std::cout << foo << std::endl;
return foo;
}
The interesting part to me was that this compiles fine in GCC 7.2 but fails on Clang 5 (complaining about non-constexpr assign of foo
).
AFAIK, since C++11, std::numeric_limits<float>::infinity()
and infinity()
are constexpr
, so I am wondering where the problem lies for Clang.
EDIT 1:
Removed unnecessary static_assert
.
Thanks for pointing to division by 0. IMO the quoted standards text there does not apply here!?
And the obligatory godbolt link: https://godbolt.org/g/Nd5yF9
EDIT 2:
Note that the same behavior applies to:
constexpr float foo = std::numeric_limits<float>::infinity() - 100.0f;
I'm not particularly familiar with floating point rules, but I'd suspect that we might be running afoul of [expr]/4:
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.
Which, in turn, means we run afoul of [expr.const]/2.6:
An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions: [...] an operation that would have undefined behavior as specified in [intro] through [cpp] of this document
That means the initializer for foo
isn't a constant expression, so we can't initialize a constexpr
object with it.
If infinity() - epsilon()
is well-defined for float
, this is a clang bug, the code is well-formed. If it's not well-defined for float
, this is a gcc bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With