patterncppCritical
What is the <=> ("spaceship", three-way comparison) operator in C++?
Viewed 0 times
comparisonthethreewayoperatorwhatspaceship
Problem
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?
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, 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:
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:
!=; otherwise return an _equality, and we’ll efficiently generate
symmetric == and !=.
is accessible using the public const members), otherwise return
weak_.
Comparison Categories
Five comparison categories are defined as
with the following predefined values:
Implicit conversions between these types are defined as follows:
Three-way comparison
The`
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).
The expression a b returns an object that 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&) const = 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
!=; 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:
strong_orderingwith values {less,equal,greater} implicitly converts to:
weak_orderingwith values {less,equivalent,greater}
partial_orderingwith values {less,equivalent,greater}
strong_equalitywith values {unequal,equal,unequal}
weak_equalitywith values {nonequivalent,equivalent,nonequivalent}
weak_orderingwith values {less,equivalent,greater} implicitly converts to:
partial_orderingwith values {less,equivalent,greater}
weak_equalitywith values {nonequivalent,equivalent,nonequivalent}
partial_orderingwith values {less,equivalent,greater,unordered} implicitly converts to:
weak_equalitywith values {nonequivalent,equivalent,nonequivalent,nonequivalent}
strong_equalitywith values {equal,unequal} implicitly converts to:
weak_equalitywith values {equivalent,nonequivalent}
Three-way comparison
The`
token is introduced. The character sequencetokenizes to, in old source code. For example,Xneeds to add a space to retain its meaning.
The overloadable operatoris a three-way comparison function and has precedence higher thanoperators defined in the language and in the standard library return one of the 5 aforementionedstd::comparison category types.
For language types, the following built-insame-type comparisons are provided. All are constexpr, except where noted otherwise. These comparisons cannot be invoked heterogeneously using scalar promotions/conversions.
- For
bool, integral, and pointer types,returnsstrong_ordering.
- For pointer types, the different cv-qualifications and derived-to-base conversions are allowed to invoke a homogeneous built-in
, and there are built-in heterogeneousoperator(T*, nullptr_t). Only comparisons of pointers to the same object/allocation are constant expressions.
- For fundamental floating point types,
returnspartial_ordering, and can be invoked heterogeneously by widening arguments to a larger floating point type.
- For enumerations,
returns the same as the enumeration's underlying type's.
- For
nullptr_t, returnsstrong_orderingand always yieldsequal.
- For copyable arrays,
T[N] T[N]returns the same type asT'sand performs lexicographical elementwise comparison. There is nofor other arrays.
- For
voidthere is no`.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).
Code Snippets
auto X::operator<=>(const Y&) const = default;┌──────────────────┬───────────────────────────────────┬─────────────┐
│ │ 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 │ │
└──────────────────┴──────┴────────────┴───────────────┴─────────────┘Context
Stack Overflow Q#47466358, score: 181
Revisions (0)
No revisions yet.