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()
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 expressiona <=> b
yields
std::partial_ordering::less
ifa
is less thanb
std::partial_ordering::greater
if a is greater thanb
std::partial_ordering::equivalent
ifa
is equivalent tob
(-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
.