namespace cpp

C++ lernen, kennen, anwenden

Benutzer-Werkzeuge

Webseiten-Werkzeuge


kennen:include:compare

<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:

  • a < b wird zu (a <=> b) < 0,
  • a > b entspricht (a <=> b) > 0 und
  • a == b ist äquivalent zu (a <=> b) == 0.

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:

  • std::strong_ordering vergleicht alle Elemente einer Struktur/Klasse,
  • std::weak_ordering erlaubt unterscheidbare Objekte, die als gleich, aber nicht ersetzbar erachtet werden, z.B. Zeichenketten, für die Groß- und Kleinschreibung ignoriert werden kann,
  • std::partial_ordering erlaubt als Vergleichsergebnis unordered: für NaNs von Gleitkommazahlen sind a<b, a==b und a>b zugleich false.

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.

kennen/include/compare.txt · Zuletzt geändert: 2020-07-25 09:37 von rrichter