В 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
нет <=>
.
Чтобы лучше понять внутреннюю работу этого оператора, пожалуйста, прочитайте оригинальную статью . Это то, что я узнал с помощью поисковых систем.