c++language-lawyernanc++20spaceship-operator

Spaceship Operator on NaN


How does C++ treat floating-point NaN when doing space-ship comparison operations? We know that the usual compares always return false, so how does this change with NaN?

std::numeric_limits<double>::quiet_NaN() <=> std::numeric_limits<double>::quiet_NaN()

Solution

  • According to cppreference, in the case of floating point arguments to the built-in <=> operator:

    [...] the operator yields a prvalue of type std::partial_ordering. The expression a <=> b yields

    • std::partial_ordering::less if a is less than b
    • std::partial_ordering::greater if a is greater than b
    • std::partial_ordering::equivalent if a is equivalent to b (-0 <=> +0 is equivalent)
    • std::partial_ordering::unordered (NaN <=> anything is unordered)

    So, in brief, applying <=> to a floating point value of NaN results in std::partial_ordering::unordered.

    When evaluating an expression like a <=> b == 0 or a <=> b < 0, if either a or b is NaN then the whole expression returns false, which makes sense coming from NaN's built-in behaviour (source). Of course, std::partial_ordering::unordered == std::partial_ordering::unordered holds true or else this type wouldn't be very useful.

    If you can otherwise guarantee the absence of pathological floating point values, take a look at this Q/A for a floating point wrapper whose comparisons yield std::strong_ordering.