Daily bit(e) C++. std::strong_ordering, std::weak_ordering, std::partial_ordering

Добавлено 27 июля 2026 в 23:33

Daily bit(e) C++ 46, типы упорядочивания, создаваемые оператором трехстороннего сравнения.

Daily bit(e) C++

Оператор «космический корабль» в C++20 обеспечивает трехстороннее сравнение, результат которого затем оборачивается в тип упорядочивания.

Стандарт предоставляет три типа упорядочивания, поскольку разные типы могут поддерживать только некоторые упорядочивания.

std::strong_ordering, для которого равенство подразумевает, что значения неразличимы (т.е. если a == b, то f(a) == f(b)).

std::weak_ordering допускает равные, различимые значения, но не допускает несравнимых значений.

std::partial_ordering, который допускает несравнимые значения (т.е. a < b, a > b и a == b возвращают false).

#include <cmath>

// Целочисленные типы строго упорядочены
using cmp_int = decltype(0 <=> 1);
// cmp_int == std::strong_ordering


struct Coord 
{
    int x;
    int y;
    friend auto operator<=>(const Coord&, const Coord&) = default;
};

// Агрегаты, образованные из сильно упорядоченных компонентов,
// также в конечном итоге оказываются сильно упорядоченными
using cmp_agg = decltype(Coord{0,0} <=> Coord{1,1});
// cmp_agg == std::strong_ordering


// Сравнение величины координаты дает лишь слабое упорядочивание,
// разные координаты имеют одинаковую величину
struct Point : Coord 
{
    int magnitude() const 
    {
        return x*x + y*y;
    }
    // int{}<=>int{} привело бы к std::strong_odering, 
    // мы должны указать упорядочивание вручную 
    friend std::weak_ordering operator<=>(
      const Point& left, const Point& right) 
    {
        return left.magnitude() <=> right.magnitude();
    }
    friend bool operator==(const Point&, const Point&) = default;
};

using cmp_mag = decltype(Point{0,1} <=> Point{1,0});
// cmp_mag == std::weak_ordering


// Следует отметить, что числа с плавающей запятой упорядочены лишь частично:
using cmp_flt = decltype(-0.0<=>0.0);
// cmp_flt == std::partial_ordering

bool r1 = -0.0 == 0.0;
bool r2 = std::signbit(-0.0) == std::signbit(0.0);
// r1 == true, r2 == false
// -0.0 и 0.0 равны, но различимы

bool r3 = NAN == 0.0 || NAN < 0.0 || NAN > 0.0;
// r3 == false, NaN не упорядочен

Пример на Compiler Explorer

Теги

C++ / CppDaily bit(e) C++Программирование