Daily bit(e) C++. std::strong_ordering, std::weak_ordering, std::partial_ordering
Добавлено 27 июля 2026 в 23:33
Daily bit(e) C++ 46, типы упорядочивания, создаваемые оператором трехстороннего сравнения.

Оператор «космический корабль» в 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 не упорядочен
