Последнее обновление:2026-10-12
Оператор трёхстороннего сравнения <=> в C++20¶
Три вида упорядоченности¶
Оператор трёхстороннего сравнения <=> называют также «оператором космического корабля»; его возвращаемое значение имеет три вида упорядоченности — ниже подробно разберём это с точки зрения исходников gcc.
Примечание: для ленивых — примеры этого раздела уже выложены в сообществе (知识星球).
Использование: <=>
#include <compare>
#include <iostream>
int main() {
auto c1 = 1.1 <=> 2.2;
auto c2 = -1 <=> 1;
std::cout << typeid(c1).name() << std::endl;
std::cout << typeid(c2).name() << std::endl;
}
Вывод:
1.1 <=> 2.2: это сравнение двух чисел с плавающей точкой. Для плавающих чисел стандартная библиотека возвращаетstd::partial_ordering, поскольку наличие NaN не делает их сравнение строгим полным порядком.std::partial_orderingдопускает результаты<,>,==илиunordered.
Мы можем посмотреть статические переменные в коде gcc, чтобы понять, что именно означает partial_ordering — меньше, больше, равно или неупорядоченно:
static const partial_ordering less;
static const partial_ordering equivalent;
static const partial_ordering greater;
static const partial_ordering unordered;
Если же выполнить принудительное преобразование, получим ошибку:
comp.cc:6:36: error: conversion from 'std::partial_ordering' to non-scalar type 'std::strong_ordering' requested
6 | std::strong_ordering c1 = 1.1 <=> 2.2;
2. `-1 <=> 1`: это сравнение двух целых чисел. Для целых чисел стандартная библиотека возвращает `std::strong_ordering`, поскольку сравнение целых — строгий полный порядок без неопределённых случаев. `std::strong_ordering` возвращает только `<`, `>` или `==`.
Аналогично можно использовать следующие 4 статических члена.
static const strong_ordering less;
static const strong_ordering equal;
static const strong_ordering equivalent;
static const strong_ordering greater;
Поэтому типом c1 является std::partial_ordering, а типом c2 — std::strong_ordering, что и объясняет, почему выведенные типы различаются.
Помимо partial_ordering и strong_ordering, <=> может возвращать и weak_ordering, со следующими статическими членами:
static const weak_ordering less;
static const weak_ordering equivalent;
static const weak_ordering greater;
equal и equivalent¶
В приведённых выше трёх ordering для равенства появилось два термина: equal и equivalent — в чём же между ними разница?
Обратимся напрямую к cppreference: различий между ними нет. Однако std::strong_ordering — единственная категория, определяющая равенство (equality). Все остальные категории определяют лишь эквивалентность. Это как раз подтверждается приведёнными выше статическими членами: у string_ordering их два, у остальных есть только equivalent.
Если сравнение даёт между сравниваемыми объектами строгий порядок, то эквивалентность и равенство совпадают. Тому есть два слова лишь потому, что для других видов упорядоченности это не так. Слабый и частичный порядки вообще не имеют равенства; они предоставляют только эквивалентность.
Эквивалентность означает, что два объекта могут сравниваться как равные. Равенство означает нечто большее: если объекты сравниваются как равные, один может быть заменён другим в любом const-использовании — пока a == b истинно, выполняется и свойство f(a) == f(b), где f обозначает функцию, читающую только сравнительно значимое состояние, доступное через публичные const-члены параметров. Если сравнение типа допускает равенство (что требуется для строгого порядка), оно допускает и эквивалентность. Поэтому для сравнения со строгим порядком они совпадают.
https://en.cppreference.com/w/cpp/utility/compare/strong_ordering
Зачем нужен оператор трёхстороннего сравнения?¶
Оператор трёхстороннего сравнения (<=>) позволяет определить отношение порядка двух значений за одну операцию, тогда как традиционным операторам сравнения потребовалось бы несколько сравнений.
Ограничения традиционных операторов сравнения:
- Если
a == bложно, вы не можете узнать,a < bэто илиa > b. - Если
a != bистинно, вы не можете узнать,a < bэто илиa > b. - Если
a < bложно, вы не можете узнать,a == bэто илиa > b. - Если
a > bложно, вы не можете узнать,a == bэто илиa < b. - Если
a <= bистинно, вы не можете узнать,a == bэто илиa < b. - Если
a >= bистинно, вы не можете узнать,a == bэто илиa > b.
Эти ограничения показывают, что традиционные операторы сравнения не могут за один раз определить полное отношение двух значений — для получения исчерпывающего результата требуется несколько сравнений.
На этом раздел закончен
Похожие темы¶
- Введение в корутины C++20 | C++那些事
- Практика с channel в C++20 | C++那些事
- Концепции Concepts в C++20 | C++那些事
- constexpr и оператор «запятая» в C++20 | C++那些事
- Порядок байтов endian в C++20 | C++那些事
- Лямбда-выражения в C++20 (часть 1) | C++那些事
- Модули Modules в C++20 | C++那些事
- Библиотека Ranges в C++20 | C++那些事
- Дизайн и подводные камни std::span в C++20 | C++那些事
- Обзор новых возможностей C++20 | C++那些事