Search code examples
c++nanconstexpr

Can runtime and constexpr nan comparisons disagree?


I was writing a constexpr bool isfinite(Float) function because I'm not on C++23 yet and so my std::isfinite isn't constexpr. But CI said MSVC didn't like something.

In general, nan should compare false with anything with all comparisons other than != which should always be true: https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN

After some digging, here's the simplest form of the problem:

#include <cassert>
#include <limits>

// Stating assumptions:
static_assert(std::numeric_limits<float>::is_iec559);
static_assert(std::numeric_limits<float>::has_quiet_NaN);
static_assert(std::numeric_limits<float>::has_infinity);
static_assert(std::is_same_v<decltype(NAN), decltype(INFINITY)>);
static_assert(std::is_same_v<float, decltype(INFINITY)>);


int main() {
    static_assert(INFINITY == std::numeric_limits<float>::infinity()); // Obviously!
    assert(INFINITY == std::numeric_limits<float>::infinity()); // Obviously.
    assert(not (NAN < std::numeric_limits<float>::infinity())); // Nan always compares false, so good.
    assert(NAN < INFINITY); // What?! This shouldn't pass!
    static_assert(NAN < INFINITY); // Neither should this!
    static_assert(NAN < std::numeric_limits<float>::infinity()); // Neither should this!
}

https://godbolt.org/z/dsqhcz18E

What the heck is going on? Am I into implementation-defined behavior?

With clang I get the errors I'd expect: https://godbolt.org/z/cvKv8ssax and same with gcc: https://godbolt.org/z/Moen3x1ov


Solution

  • Am I into implementation-defined behavior?

    From C++ perspective: Yes, sort of. The non-finite floating point comparisons are not defined by the C++ standard. That said, static_assert(std::numeric_limits<float>::is_iec559) brings in another standard into consideration.

    From IEC 559 aka IEEE-754 perspective: No, the comparisons are defined by this standard, so they aren't implementation defined.

    What the heck is going on?

    Looks like a bug in the language implementation.