Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
202 lines (165 sloc) 3.82 KB

Spaceship Operator

Before C++20 After C++20
class MyInt {
    int value = 0;

public:
    friend bool operator==(MyInt a, MyInt b) {
        return a.value == b.value;
    }

    friend bool operator!=(MyInt a, MyInt b) {
        return !(a == b);
    }

    friend bool operator<(MyInt a, MyInt b) {
        return a.value < b.value;
    }

    friend bool operator<=(MyInt a, MyInt b) {
        return !(b < a);
    }

    friend bool operator>(MyInt a, MyInt b) {
        return b < a;
    }

    friend bool operator>=(MyInt a, MyInt b) {
        return !(a < b);
    }
};
class MyInt {
    int value = 0;

public:
    auto operator<=>(MyInt) const = default;
};

Details

Usage

C++20 introduces the three-way comparison operator, also known as the "spaceship operator":

class Person {
    std::string lastname;
    std::string firstname;

public:
    auto operator<=>(Person const&) const = default;
};

The spaceship operator behaves similarly to strcmp and memcmp:

strcmp/memcmp operator<=> Meaning
if (strcmp(a, b) < 0);
if (auto cmp = a <=> b; cmp < 0);

If a is less than b.

if (strcmp(a, b) > 0);
if (auto cmp = a <=> b; cmp > 0);

If a is greater than b.

if (strcmp(a, b) == 0);
if (auto cmp = a <=> b; cmp == 0);

If a is equal to b.

Thanks to Symmetry for Spaceship [P0905], if a <=> b is well-formed, then b <=> a is also well-formed. This means only one definition of operator<=> is required to provide heterogeneous type comparison (it does not need to be a (friend-ed) non-member function).

Existing equality and comparison operator overloads take precedence over the spaceship operator. This means this is not a breaking change, and users can still specialize particular operators as desired.

Note

The spaceship operator resembles a TIE bomber <=>, not a TIE fighter |=|.

Comparison Categories

C++20 also introduces comparison categories to specify regarding weak/partial/strong ordering and weak/strong equality.

Before C++20 After C++20
template <typename T>
class LinkedList<T>::iterator {
    Node<T>* ptr = nullptr;

public:
    friend bool operator==(iterator const& other) {
        return ptr == other.ptr;
    }

    friend bool operator!=(iterator const& other) {
        return ptr != other.ptr;
    }
};
template <typename T>
class LinkedList<T>::iterator {
    Node<T>* ptr = nullptr;

public:
    std::strong_equality operator<=>(iterator const&) const = default;
};

Comparison categories implicitly convert to corresponding AS-IF categories, e.g. std::strong_ordering implies/is implicitly convertible to std::strong_equality and std::weak_ordering.

Note

Descriptions and examples heavily reference the original paper, Consistent Comparison [P0515].