Проверить, является ли тип частичным заказом - PullRequest
3 голосов
/ 05 мая 2020

Можно ли проверить тип на свойство частичного упорядочивания в C ++ 20? Если да, то как можно провести такую ​​проверку с использованием концептов?

Достаточно ли для этой цели следующего кода?

#include <compare>
#include <concepts>

template<class T>
concept PartialOrder = requires (const T& lhs, const T& rhs) {
  // Is there any caveat in this?
  { lhs <=> rhs } -> std::convertible_to<std::partial_ordering>;
};

1 Ответ

6 голосов
/ 05 мая 2020

Такая концепция уже есть в стандартной библиотеке : three_way_comparable. T удовлетворяет three_way_comparable, если все операторы двоичного сравнения и <=> все являются допустимыми выражениями, а вызов <=> дает вам как минимум std::partial_ordering.

Это немного сложнее, чем тот, который вы предлагаете - частично, чтобы избежать странных типов (например, может быть, какой-то тип определяет operator<=>, но также удаляет operator<= по какой-либо причине? Давайте просто исключим их ...), но также из-за наличия порядка требовать равенства тоже довольно разумно. Просто потому, что тип упорядочен только частично, он не может поддерживать ==.

Еще один момент: ваш PartialOrder<T&> на самом деле сравнивает неконстантные объекты типа T, а не const. Что не идеально. Вот почему в стандарте это const remove_reference_t<T>& танцует.

Обратите внимание, что ни то, что вы предлагаете, ни концепция стандартной библиотеки не проверяет, является ли тип только частично упорядоченным, просто это минимум заказано частично. int удовлетворяет как std::three_way_comparable, так и вашу PartialOrder концепции, несмотря на очевидный полный порядок.

Один из способов добиться правильного включения в эту конкретную концепцию:

template <typename T>
concept partially_ordered = std::three_way_comparable<T>;

template <typename T>
concept totally_ordered = partially_ordered<T> &&
    requires (std::remove_cvref_t<T> const& lhs, std::remove_cvref_t<T> const& rhs) {
        { lhs <=> rhs } -> std::convertible_to<std::weak_ordering>;
    };

Или быть более ленивым:

template <typename T>
concept totally_ordered = partially_ordered<T> &&
    std::three_way_comparable<T, std::weak_ordering>;

Возможно, заменив weak_ordering на strong_ordering.

Также обратите внимание, что существует концепция std::totally_ordered, но она не требует <=>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...