Такая концепция уже есть в стандартной библиотеке : 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
, но она не требует <=>
.