Inhaltsverzeichnis

<compare>

Dreiwegevergleich

Binde diesen Header ein, um den Dreiwegevergleich ("spaceship" operator <=>) für eigene Typen zu definieren. Vergleiche auf Ordnungsrelationen und (Un-)Gleichheit, evtl. auch zum Vergleich mit anderen Typen, werden ab C++20 zusammengefasst:

Alle Vergleichsoperatoren werden damit nutzbar. Der Operator kann vom Compiler generiert

spaceship_default.cpp
#include <compare>
#include <cassert>
 
struct Foo
{
    int x, y;
    auto operator<=>(const Foo&) const = default;
};
 
int main()
{
    Foo a{1,3}, b{2,1};
 
    assert(
         (a < b)  &&
         (a <= b) &&
        !(a == b) &&
         (a != b) &&
        !(a >= b) &&
        !(a > b)
    );
}

oder selbst definiert werden. Dann wird der Gleichheitsoperator nicht automatisch mit generiert:

spaceship_own.cpp
#include <compare>
#include <cassert>
 
struct rational
{
    int d = 0, n = 1;
    auto operator<=>(const rational& b) const { return d * b.n <=> n * b.d; }
    bool operator== (const rational& b) const { return d * b.n ==  n * b.d; }
    auto operator<=>(int number) const { return d <=> n * number; }
    bool operator== (int number) const { return d ==  n * number; }
};
 
int main()
{
    rational a, b{1, 2};
    assert( a != b && 1 > b );
}

Auch Vergleiche mit anderen Typen können überladen werden. Unterscheiden sich die Typen der Operanden, sind sowohl x <=> y und y <=> x nutzbar: Aus 1 > b würde (1 <=> b) > 0. Da aber kein operator<=>(int, rational) definiert ist, schreibt der Compiler dies zu 0 > (b <=> 1) um.

Kategorien

Der Header <compare> definiert mehrere mögliche Ergebnistypen für den Dreiwegevergleich:

Der vom Compiler erzeugte Vergleich liefert das lexikographische Ergebnis der Komponenten in der Reihenfolge ihrer Definition. Als Rückgabetyp kommt die stärkste gemeinsame Vergleichskategorie zum Einsatz.

Funktionsadapter

Die Struktur compare_three_way besitzt einen Funktionsoperator operator()(T&& t, U&& u), der für Objekte beliebiger Typen den Spaceship-Vergleich t <=> u aufrufen kann, sofern dieser definiert ist. Vergleiche dazu Funktionsadapter wie less<>, greater<> usw.