Что такое оператор <=> в С++?
Пока я пытался узнать о операторах С++, я наткнулся на странный оператор сравнения на cppreference.com, * в таблице, которая выглядит так:
"Ну, если это обычные операторы на С++, я лучше их узнаю", - подумал я. Но все мои попытки разъяснить эту тайну были безуспешными. Даже здесь, в Stack Overflow, мне не повезло в моем поиске.
Есть ли связь между <= > и С++?
И если есть, что делает этот оператор точно?
* Тем временем cppreference.com обновил эту страницу и теперь содержит информацию об операторе <=>
.
Ответы
Ответ 1
Это называется оператором трехстороннего сравнения.
В соответствии с предложением P0515:
Это новый трехпозиционный оператор сравнения <=>
. Выражение a <=> b
возвращает объект, который сравнивает <0
, если a < b
, сравнивает >0
, если a > b
, и сравнивает ==0
, если a
и b
равны/эквивалентны.
Чтобы написать все сравнения для вашего типа, просто напишите operator<=>
, что возвращает соответствующий тип категории:
-
Возвращаем a_ordering, если ваш тип естественно поддерживает <
и эффективно генерирует <
, >
, <=
, >=
, ==
и !=
; в противном случае верните _equality и хорошо сгенерируйте == и !=.
-
Возвратитесь сильным, если для вашего типа a == b
подразумевается f(a) == f(b)
(заменимость, где f читает только сравнительное состояние доступный с использованием интерфейса nonprivate const), в противном случае возврат слабый.
cppreference говорит:
Операторы выражения трехстороннего сравнения имеют вид
lhs <=> rhs (1)
Выражение возвращает объект, который
- сравнивает
<0
, если lhs < rhs
- сравнивает
>0
, если lhs > rhs
- и сравнивает
==0
, если lhs
и rhs
равны/эквивалентны.
Ответ 2
В 2017-11-11, комитет ISO С++ принял Herb Sutter для оператора трехмерного сравнения <= = > " как одного из новых функций, добавленных в С++ 20, В документе под названием Согласованное сравнение Sutter, Maurer и Brown демонстрируют концепции нового дизайна. Для обзора предложения здесь выдержка из статьи:
Выражение a <= > b возвращает объект, который сравнивает < 0, если a < b, сравнивает 0, если a > b, и сравнивает == 0, если a и b равный/эквивалент.
Общий случай: Чтобы написать все сравнения для вашего типа X с типом Y, с семантикой с поправкой, просто напишите:
auto X::operator<=>(const Y&) =default;
Расширенные случаи: Чтобы написать все сравнения для вашего типа X с типом Y, просто напишите оператор <= > , который принимает Y, может использовать = по умолчанию, чтобы получить посылку семантики по желанию, и возвращает соответствующий тип категории:
- Верните _дополнительский, если ваш тип поддерживает < и эффективно генерирует симметричные <, > > , < =, =, == и =!; в противном случае верните _equality и эффективно сгенерируйте симметричный == и !=.
- Возвращает strong _, если для вашего типа a == b подразумевается f (a) == f (b) (заменимость, где f читает только сравнительное состояние, которое доступно с помощью общедоступных const участников), в противном случае возврат слабый _.
Категории сравнения
Пять категорий сравнения определяются как типы 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
нет <=>
.
Этот ответ "строится".
Чтобы лучше понять внутреннюю работу этого оператора, прочитайте оригинал paper.
Ответ 3
Этот ответ стал неактуальным, поскольку ссылка на веб-страницу изменилась
Страница веб-страницы, на которую вы ссылаетесь, была нарушена. В тот день его редактировали много, а разные части не синхронизировались. Статус, когда я смотрел на него, был:
В верхней части страницы перечислены существующие операторы сравнения (в С++ 14). Там нет <=>
.
В нижней части страницы они должны были указать те же самые операторы, но они goofed и добавили это будущее предложение.
gcc
пока не знает о <=>
(и с -std=c++14
, никогда не будет), поэтому
он думает, что вы имели в виду a <= > b
. Это объясняет сообщение об ошибке.
Если вы попробуете то же самое через пять лет, вы, вероятно, получите лучшее сообщение об ошибке, что-то вроде <=> not part of C++14.