Почему был введен std::range::less?
На cppreference наstd::ranges::less
, в примечаниях мы видим, что:
В отличие от
std::less
,std::ranges::less
требует всех шести операторов сравнения<
,<=
,>
,>=
,==
а также!=
быть действительным (черезtotally_ordered_with
ограничение).
Но почему? Зачем нам использоватьstd::ranges::less{}
вместо того std::less{}
? В какой практической ситуации мы хотимless{}
только если определены другие операторы сравнения, а не только <
один?
2 ответа
В какой практической ситуации мы хотим уменьшить {}, только если определены другие операторы сравнения, а не только
Не все в библиотеке Ranges основано исключительно на "практических" аспектах. Во многом это делается для того, чтобы сделать язык и библиотеку логичными.
Понятия как функция языка дают стандартной библиотеке возможность определять значимые комбинации свойств объекта. Сказать, что у типа естьoperator<
полезен с чисто практической точки зрения, поскольку он сообщает, какие операции ему доступны. Но на самом деле это не говорит ничего значимого о типе.
Если тип полностью упорядочен, это логически означает, что вы можете использовать любой из операторов сравнения для сравнения двух объектов этого типа. Под идеей тотального порядка,a < b
а также b > a
являются эквивалентными заявлениями. Таким образом, имеет смысл, что если код ограничен типами, которые обеспечивают полный порядок, этому коду должно быть разрешено использовать любой оператор.
ranges::less::operator()
не использует никаких операторов кроме<
. Но эта функция ограничена типами, моделирующимиtotally_ordered
концепция. Это ограничение существует, потому что это то, чтоranges::less
предназначен для: сравнения полностью упорядоченных типов. Это могло бы иметь более узкое ограничение, но это отбросило бы любой смысл, обеспечиваемый полным упорядочением.
Это также предотвращает раскрытие пользователям произвольных деталей реализации. Например, предположим, что у вас есть шаблон, который принимает некоторый типT
и вы хотите использовать T
в ranges::less
-основная работа. Если вы ограничите этот шаблон только наличиемoperator<
, то вы фактически поместили свою реализацию в ограничение. У вас больше нет возможности переключиться на реализациюranges::greater
внутренне. Если бы вы положилиstd::totally_ordered
в вашем ограничении вы должны дать понять пользователю, что ему нужно делать, предоставив себе свободу использовать любые функторы, которые вам нужны.
И с тех пор operator<=>
существует и позволяет легко реализовать операторы упорядочения в одной функции, практических недостатков нет. Ну, за исключением кода, который должен компилироваться как на C++17, так и на C++20.
По сути, вы не должны писать типы, которые "упорядочиваются" простым написанием operator<
начать с.
Насколько я могу судить на основании предложения, идея состоит в том, чтобы просто упростить дизайн функциональных объектов.std::less
- это класс шаблона, который требует параметра шаблона и представляет собой однородное сравнение. Этот параметр шаблона можно не указывать по умолчанию.std::less<void>
что позволяет проводить разнородные сравнения. Аргумент, похоже, состоит в том, что в однородном случае нет необходимости, поскольку он отлично обрабатывается гетерогенным подходом, поэтому дизайн можно значительно упростить, а шаблон класса вообще не нужен.
Что касается того, почему другие операторы, кроме operator<
требуются, я не совсем уверен. Я предполагаю, что это лишь часть того, что значит иметь общий порядок, определенный в C++ между двумя, возможно, разными типами.