18 Concepts library [concepts]

18.5 Comparison concepts [concepts.compare]

18.5.1 General [concepts.compare.general]

This subclause describes concepts that establish relationships and orderings on values of possibly differing object types.

18.5.2 Concept boolean [concept.boolean]

The boolean concept specifies the requirements on a type that is usable in Boolean contexts.
template<class B> concept boolean = movable<remove_cvref_t<B>> && // (see [concepts.object]) requires(const remove_reference_t<B>& b1, const remove_reference_t<B>& b2, const bool a) { { b1 } -> convertible_to<bool>; { !b1 } -> convertible_to<bool>; { b1 && b2 } -> same_as<bool>; { b1 && a } -> same_as<bool>; { a && b2 } -> same_as<bool>; { b1 || b2 } -> same_as<bool>; { b1 || a } -> same_as<bool>; { a || b2 } -> same_as<bool>; { b1 == b2 } -> convertible_to<bool>; { b1 == a } -> convertible_to<bool>; { a == b2 } -> convertible_to<bool>; { b1 != b2 } -> convertible_to<bool>; { b1 != a } -> convertible_to<bool>; { a != b2 } -> convertible_to<bool>; };
For some type B, let b1 and b2 be lvalues of type const remove_­reference_­t<B>.
B models boolean only if
  • bool(b1) == !bool(!b1).
  • (b1 && b2), (b1 && bool(b2)), and (bool(b1) && b2) are all equal to (bool(b1) && bool(b2)), and have the same short-circuit evaluation.
  • (b1 || b2), (b1 || bool(b2)), and (bool(b1) || b2) are all equal to (bool(b1) || bool(b2)), and have the same short-circuit evaluation.
  • bool(b1 == b2), bool(b1 == bool(b2)), and bool(bool(b1) == b2) are all equal to (bool(b1) == bool(b2)).
  • bool(b1 != b2), bool(b1 != bool(b2)), and bool(bool(b1) != b2) are all equal to (bool(b1) != bool(b2)).
Example
:
The types bool, true_­type ([meta.type.synop]), and bitset<N>​::​reference ([template.bitset]) are boolean types.
Pointers, smart pointers, and types with only explicit conversions to bool are not boolean types.
— end example
 ]

18.5.3 Concept equality_­comparable [concept.equalitycomparable]

template<class T, class U> concept weakly-equality-comparable-with = // exposition only requires(const remove_reference_t<T>& t, const remove_reference_t<U>& u) { { t == u } -> boolean; { t != u } -> boolean; { u == t } -> boolean; { u != t } -> boolean; };
For some types T and U, let t and u be lvalues of types const remove_­reference_­t<T> and const remove_­reference_­t<U> respectively.
T and U model weakly-equality-comparable-with<T, U> only if
  • t == u, u == t, t != u, and u != t have the same domain.
  • bool(u == t) == bool(t == u).
  • bool(t != u) == !bool(t == u).
  • bool(u != t) == bool(t != u).
template<class T> concept equality_comparable = weakly-equality-comparable-with<T, T>;
Let a and b be objects of type T.
T models equality_­comparable only if bool(a == b) is true when a is equal to b ([concepts.equality]), and false otherwise.
Note
:
The requirement that the expression a == b is equality-preserving implies that == is transitive and symmetric.
— end note
 ]
template<class T, class U> concept equality_comparable_with = equality_comparable<T> && equality_comparable<U> && common_reference_with<const remove_reference_t<T>&, const remove_reference_t<U>&> && equality_comparable< common_reference_t< const remove_reference_t<T>&, const remove_reference_t<U>&>> && weakly-equality-comparable-with<T, U>;
For some types T and U, let t be an lvalue of type const remove_­reference_­t<T>, u be an lvalue of type const remove_­reference_­t<U>, and C be:
common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>
T and U model equality_­comparable_­with<T, U> only if bool(t == u) == bool(C(t) == C(u)).

18.5.4 Concept totally_­ordered [concept.totallyordered]

template<class T> concept totally_ordered = equality_comparable<T> && requires(const remove_reference_t<T>& a, const remove_reference_t<T>& b) { { a < b } -> boolean; { a > b } -> boolean; { a <= b } -> boolean; { a >= b } -> boolean; };
For some type T, let a, b, and c be lvalues of type const remove_­reference_­t<T>.
T models totally_­ordered only if
  • Exactly one of bool(a < b), bool(a > b), or bool(a == b) is true.
  • If bool(a < b) and bool(b < c), then bool(a < c).
  • bool(a > b) == bool(b < a).
  • bool(a <= b) == !bool(b < a).
  • bool(a >= b) == !bool(a < b).
template<class T, class U> concept totally_ordered_with = totally_ordered<T> && totally_ordered<U> && common_reference_with<const remove_reference_t<T>&, const remove_reference_t<U>&> && totally_ordered< common_reference_t< const remove_reference_t<T>&, const remove_reference_t<U>&>> && equality_comparable_with<T, U> && requires(const remove_reference_t<T>& t, const remove_reference_t<U>& u) { { t < u } -> boolean; { t > u } -> boolean; { t <= u } -> boolean; { t >= u } -> boolean; { u < t } -> boolean; { u > t } -> boolean; { u <= t } -> boolean; { u >= t } -> boolean; };
For some types T and U, let t be an lvalue of type const remove_­reference_­t<T>, u be an lvalue of type const remove_­reference_­t<U>, and C be:
common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>
T and U model totally_­ordered_­with<T, U> only if
  • bool(t < u) == bool(C(t) < C(u)).
  • bool(t > u) == bool(C(t) > C(u)).
  • bool(t <= u) == bool(C(t) <= C(u)).
  • bool(t >= u) == bool(C(t) >= C(u)).
  • bool(u < t) == bool(C(u) < C(t)).
  • bool(u > t) == bool(C(u) > C(t)).
  • bool(u <= t) == bool(C(u) <= C(t)).
  • bool(u >= t) == bool(C(u) >= C(t)).