Подтвердить что ты не робот

Почему для Сортируемой концепции требуется полностью упорядоченный тип значения, в то время как std:: sort требует только "меньше" сопоставимого?

В последней статье по концепциям N3701 приведен следующий пример с алгоритмом sort:

template<typename Cont>
  requires Sortable<Cont>()
void sort(Cont& cont)

где Sortable понятие определяется как

template<typename T>
concept bool Sortable()
{
  return Permutable_container<T>() && Totally_ordered<Value_type<T>>();
}

где Totally_ordered, что неудивительно, определяется как

template<typename T>
constexpr bool Totally_ordered()
{
  return Weakly_ordered<T>() && Equality_comparable<T>();
}

и, в свою очередь, Equality_comparable определяется как

template<typename T>
constexpr bool Equality_comparable()
{
  return requires(T a, T b) {
    {a == b} -> bool;
    {a != b} -> bool;
  };
}

Я не нашел определения Weakly_ordered, но я считаю, что он должен выглядеть так (я прав?)

template<typename T>
constexpr bool Weakly_ordered()
{
  return requires(T a, T b) {
    {a < b} -> bool;
    {a <= b} -> bool;
    {a > b} -> bool;
    {a >= b} -> bool;
  };
}

Нижняя строка, в этом определении, если я хочу сортировать std::vector<T>, мне нужно T, чтобы предоставить все операторы сравнения <, <=, >, >=, ==, !=, Однако в течение всей жизни С++ std::sort должен быть предоставлен только оператор <! Вот что cppreference говорит о std::sort:

Сортирует элементы в диапазоне [первый, последний] в порядке возрастания. порядок равных элементов не гарантируется. Первый версия использует оператор < для сравнения элементов, вторая версия использует данный объект сравнения comp comp.

Итак, что это значит, что в будущем С++ с концепциями для v типа std::vector<T>, где T предоставляет только operator<, std::sort(v.begin(), v.end()) будет компилироваться, а std::sort(v) не будет? Это звучит безумно.

Я проверил это в текущей версии range-v3 от Эрика Ниблера, и он работает так, как я описал. Код не компилируется, если не указаны все операторы.

См. также соответствующее обсуждение: https://github.com/ericniebler/range-v3/issues/271

4b9b3361

Ответ 1

Концепции TS не концептуализируют стандартную библиотеку. Это был просто пример; ничего более.

В версии Ranges TS sort требуется Sortable, которая по умолчанию сравнивает свой класс сравнения с std::less<>. Однако, казалось бы, std::less<>::operator() налагает требование TotallyOrdered на типы его параметров. Так, откуда он исходит. Там есть примечание об этом в P0021R0 (PDF):

[Примечание редактора: Удалить таблицу [lessthancomparable] в [utility.arg.requirements]. Замените использование LessThanComparable с помощью TotallyOrdered (, признавая, что это изменение прерывания, которое делает требования типа более строгими). Заменить ссылки на [lessthancomparable] со ссылками на [concept.lib.compare.totallyordered]]

Добавлен акцент. Общие проблемы, связанные с этим отображаются в ожидании в ожидании других языковых функций (например, неявное создание всех других операторов, основанных исключительно на operator< или somesuch).

Вы можете просто использовать (нормальную) версию функции сравнения. Или вы можете просто использовать версию itator std::sort, которая не будет использовать какие-либо понятия.


Следует также отметить, что с введение "оператор космического корабля" на С++ 20 (самое раннее, что мы могли видеть, что TS диапазона интегрирован в стандарт), все это обсуждение эффективно становится спорным. Простое объявление auto operator<=>(const MyType &) = default; в классе, и вдруг ваш тип полностью упорядочен.