For a concrete example of what this looks like, check out the Homer Simpson -designed "everything" car.
https://media.wired.com/photos/593252a1edfced5820d0fa07/mast...
p.s. Fascinating bug! One of the most interesting cases I've encountered.
For a concrete example of what this looks like, check out the Homer Simpson -designed "everything" car.
https://media.wired.com/photos/593252a1edfced5820d0fa07/mast...
p.s. Fascinating bug! One of the most interesting cases I've encountered.
Historically C++ only had these separate comparison operators, and operator overloading, and so if you want ordering you'd be expected to override all of the operators and do so in a consistent way. Turns out it's easy enough to get that wrong and if you do now your C++ program is often nonsense, it has no defined meaning whatsoever. For example if a < b && b < a then too bad now many built-in library functions might do absolutely anything in say C++ 17.
With the spaceship operator you're still screwed if your type provides an incoherent ordering (unlike Rust where that just means the type is less useful) but it's much more likely you'll write something which actually works.
There are times that doesn’t work, so documentation usually has a footnote that (1) certain algorithms require a partial ordering and not necessarily a total ordering, and (2) to use those algorithms, you must implement less-than, but any other comparison operator is ignored by the algorithm; instead, less-than is used to figure out greater-than and equal-to as needed. This was considered better than requiring programmers to implement a collection of comparison operators, and trusting those programmers to make those operators act consistently with each other (e.g., never say that “a” and “b” are both less-than and greater-than each other).
The spaceship operator seems to address this specific case ( https://open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0515r0... ). According to Herb Sutter (note that his name is on the proposal), “We added the C++20 spaceship operator to the language, but we also applied it throughout the C++ standard library and that made the library specification nearly 20 pages shorter — a net reduction” ( https://herbsutter.com/2020/12/ ).
The main things I've actually had to watch out for are floating point values that could have not-a-numbers (e.g., https://en.cppreference.com/w/cpp/numeric/math/isunordered.h... ), and possibly Unicode strings that aren't normalized ( https://unicode.org/reports/tr15/ ), but those act weird in all software I'm familiar with. Because people forget about the relevant edge cases.
#define isNan(X) ((X) != (X))> #define isNan(X) ((X) != (X))
> Works by exploiting a unique property of NaN (Not a Number) values in the IEEE-754 floating point standard: a NaN is not equal to itself. In other words, if you compare a floating-point variable to itself and the result is false ((X) != (X)(X)!=(X)), then X X is NaN.
Fantastic example, thank you @spyrja!