There already is such a concept in the standard library: three_way_comparable
. T
satisfies three_way_comparable
if all the binary comparison operators and <=>
are all valid expressions and the invocation of <=>
gives you at least std::partial_ordering
.
It's a little bit more involved than the one you're proposing - partially to avoid weird types (e.g. maybe some type defines operator<=>
but also deletes operator<=
for whatever reason? Let's just exclude those...) but also because having an ordering require equality is also pretty sensible. Just because a type is only partially ordered doesn't need it can't support ==
as well.
One other point is your PartialOrder<T&>
actually ends up comparing non-const objects of type T
, rather than const
ones. Which isn't ideal. That's why the standard does this const remove_reference_t<T>&
dance.
Note that neither what you're suggesting nor the standard library concept checks that a type is only partially ordered, just that it's at least partially ordered. int
satisfies both std::three_way_comparable
and your PartialOrder
concepts, despite obviously having a total order.
One way of achieving proper subsumption with this particular concept is:
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>;
};
Or to be lazier:
template <typename T>
concept totally_ordered = partially_ordered<T> &&
std::three_way_comparable<T, std::weak_ordering>;
Possibly by replacing weak_ordering
with strong_ordering
.
Also note that there is a std::totally_ordered
concept - but it does not require <=>
.