c++operatorsc++20spaceship-operator

What is the <=> ("spaceship", three-way comparison) operator in C++?


While I was trying to learn about C++ operators, I stumbled upon the following table that listed a strange comparison operator. What does this <=> operator do?

2017 image of a table from cppreference.com Since 2017 cppreference.com updated that page and now contains detailed information about the<=>operator.


Solution

  • On 2017-11-11, the ISO C++ committee adopted Herb Sutter's proposal for the <=> "spaceship" three-way comparison operator as one of the new features that were added to C++20. In the paper titled Consistent comparison Sutter, Maurer and Brown demonstrate the concepts of the new design. For an overview of the proposal, here's an excerpt from the article:

    The expression a <=> b returns an object that compares <0 if a < b, compares >0 if a > b, and compares ==0 if a and b are equal/equivalent.

    Common case: To write all comparisons for your type X with type Y, with memberwise semantics, just write:

    auto X::operator<=>(const Y&) =default;
    

    Advanced cases: To write all comparisons for your type X with type Y, just write operator<=> that takes a Y, can use =default to get memberwise semantics if desired, and returns the appropriate category type:

    • Return an _ordering if your type naturally supports <, and we’ll efficiently generate symmetric <, >, <=, >=, ==, and !=; otherwise return an _equality, and we’ll efficiently generate symmetric == and !=.
    • Return strong_ if for your type a == b implies f(a) == f(b) (substitutability, where f reads only comparison-salient state that is accessible using the public const members), otherwise return weak_.
    Comparison Categories

    Five comparison categories are defined as std:: types, with the following predefined values:

    ┌──────────────────┬───────────────────────────────────┬─────────────┐
    │                  │          Numeric  values          │ Non-numeric │
    │     Category     ├──────┬────────────┬───────────────┤             │
    │                  │ -1   │ 0          │ +1            │   values    │
    ├──────────────────┼──────┼────────────┼───────────────┼─────────────┤
    │ strong_ordering  │ less │ equal      │ greater       │             │
    │ weak_ordering    │ less │ equivalent │ greater       │             │
    │ partial_ordering │ less │ equivalent │ greater       │ unordered   │
    │ strong_equality  │      │ equal      │ nonequal      │             │
    │ weak_equality    │      │ equivalent │ nonequivalent │             │
    └──────────────────┴──────┴────────────┴───────────────┴─────────────┘
    

    Implicit conversions between these types are defined as follows:

    Three-way comparison

    The<=>token is introduced. The character sequence<=>tokenizes to<= >, in old source code. For example,X<&Y::operator<=>needs to add a space to retain its meaning.

    The overloadable operator<=>is a three-way comparison function and has precedence higher than< and lower than<<. It returns a type that can be compared against literal0but other return types are allowed such as to support expression templates. All<=>operators defined in the language and in the standard library return one of the 5 aforementionedstd::comparison category types.

    For language types, the following built-in<=>same-type comparisons are provided. All are constexpr, except where noted otherwise. These comparisons cannot be invoked heterogeneously using scalar promotions/conversions.

    To better understand the inner workings of this operator, please read the original paper. This is just what I've found out using search engines. Also, check out Comparison Operators, including Three-Way Comparison(C++20).