В 2017-11-11 комитет ISO C ++ принял предложение Херба Саттера о трехстороннем операторе сравнения "космический корабль" <=> в качестве одной из новых функций, добавленных в C ++ 20 . В статье под названием « Последовательное сравнение» Саттер, Маурер и Браун демонстрируют концепции нового дизайна. Для обзора предложения, вот выдержка из статьи:
Выражение a <=> b возвращает объект, который сравнивает <0, если a <b , сравнивает > 0, если a> b , и сравнивает == 0, если a и b равны / эквивалентны.
Распространенный случай: чтобы написать все сравнения для вашего типа X с типом Y с семантикой по элементам, просто напишите:
auto X::operator<=>(const Y&) =default;
Дополнительные случаи: чтобы написать все сравнения для вашего типа X с типом Y , просто напишите оператор <=>, который принимает Y , может использовать
= default для получения семантики для каждого элемента, если это необходимо, и возвращает соответствующий тип категории:
- Верните _ordering, если ваш тип естественным образом поддерживает < , и мы будем эффективно генерировать симметричные < , > , <= , > = , == и
! = ; в противном случае верните _equality , и мы будем эффективно генерировать симметричные == и ! = .
- Возврат strong_ если для вашего типа A == B означает F (а) == е (б) (взаимозаменяемость, где е читает только сравнительную-выступ состояния, которое доступно с помощью общественных константные членов), в противном случае вернуть
weak_ .
Категории сравнения
Пять категорий сравнения определены как std::типы, каждая из которых имеет следующие предопределенные значения:
+--------------------------------------------------------------------+
| | Numeric values | Non-numeric |
| Category +-----------------------------------+ |
| | -1 | 0 | +1 | values |
+------------------+------+------------+---------------+-------------+
| strong_ordering | less | equal | greater | |
| weak_ordering | less | equivalent | greater | |
| partial_ordering | less | equivalent | greater | unordered |
| strong_equality | | equal | nonequal | |
| weak_equality | | equivalent | nonequivalent | |
+------------------+------+------------+---------------+-------------+
Неявные преобразования между этими типами определяются следующим образом:
strong_orderingсо значениями { less, equal, greater} неявно преобразует в:
weak_orderingсо значениями { less, equivalent, greater}
partial_orderingсо значениями { less, equivalent, greater}
strong_equalityсо значениями { unequal, equal, unequal}
weak_equalityсо значениями { nonequivalent, equivalent, nonequivalent}
weak_orderingсо значениями { less, equivalent, greater} неявно преобразует в:
partial_orderingсо значениями { less, equivalent, greater}
weak_equalityсо значениями { nonequivalent, equivalent, nonequivalent}
partial_orderingсо значениями { less, equivalent, greater, unordered} неявно преобразует в:
weak_equalityсо значениями { nonequivalent, equivalent, nonequivalent, nonequivalent}
strong_equalityсо значениями { equal, unequal} неявно преобразуется в:
weak_equalityсо значениями { equivalent, nonequivalent}
Трехстороннее сравнение
<=>Маркер вводится. Последовательность символов <=>токенизируется <= >в старом исходном коде. Например, X<&Y::operator<=>необходимо добавить пробел, чтобы сохранить его значение.
Перегружаемый оператор <=>является трехсторонней функцией сравнения и имеет приоритет выше <и ниже, чем <<. Он возвращает тип, который можно сравнить с литералом, 0но допускаются и другие возвращаемые типы, например, для поддержки шаблонов выражений. Все <=>операторы, определенные на языке и в стандартной библиотеке, возвращают один из 5 вышеупомянутых std::типов категорий сравнения.
Для языковых типов предусмотрены следующие встроенные <=>сравнения одного типа. Все являются constexpr , если не указано иное. Эти сравнения не могут быть вызваны гетерогенно, используя скалярные продвижения / преобразования.
- Для
bool, целочисленный и указатель типов <=>возвращает strong_ordering.
- Для типов указателей различные cv-квалификации и преобразования из производных в базовые могут вызывать однородные встроенные
<=>, а встроенные гетерогенные operator<=>(T*, nullptr_t). Только сравнения указателей на один и тот же объект / распределение являются константными выражениями.
- Для фундаментальных типов с плавающей запятой
<=>возвращается partial_orderingи может вызываться неоднородно путем расширения аргументов до большего типа с плавающей запятой.
- Для перечислений
<=>возвращает то же, что и базовый тип перечисления <=>.
- Для
nullptr_t, <=>возвратов strong_orderingи всегда дает equal.
- Для копируемых массивов
T[N] <=> T[N]возвращает тот же тип, что Tи s, <=>и выполняет лексикографическое поэлементное сравнение. Нет <=>для других массивов.
- Ибо
voidнет <=>.
Чтобы лучше понять внутреннюю работу этого оператора, пожалуйста, прочитайте оригинальную статью . Это то, что я узнал с помощью поисковых систем.