7 Concepts library [concepts.lib]

7.4 Comparison concepts [concepts.lib.compare]

7.4.1 General [concepts.lib.compare.general]

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

7.4.2 Concept Boolean [concepts.lib.compare.boolean]

The Boolean concept specifies the requirements on a type that is usable in Boolean contexts.

template <class B> concept bool Boolean = Movable<decay_t<B>> && // (see [concepts.lib.object.movable]) requires(const remove_reference_t<B>& b1, const remove_reference_t<B>& b2, const bool a) { { b1 } -> ConvertibleTo<bool>&&; { !b1 } -> ConvertibleTo<bool>&&; { b1 && a } -> Same<bool>&&; { b1 || a } -> Same<bool>&&; { b1 && b2 } -> Same<bool>&&; { a && b2 } -> Same<bool>&&; { b1 || b2 } -> Same<bool>&&; { a || b2 } -> Same<bool>&&; { b1 == b2 } -> ConvertibleTo<bool>&&; { b1 == a } -> ConvertibleTo<bool>&&; { a == b2 } -> ConvertibleTo<bool>&&; { b1 != b2 } -> ConvertibleTo<bool>&&; { b1 != a } -> ConvertibleTo<bool>&&; { a != b2 } -> ConvertibleTo<bool>&&; };

Given const lvalues b1 and b2 of type remove_reference_t<B>, then Boolean<B> is satisfied 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, std::true_type, and std::bitset<N>::reference are Boolean types. Pointers, smart pointers, and types with explicit conversions to bool are not Boolean types. — end example ]

7.4.3 Concept EqualityComparable [concepts.lib.compare.equalitycomparable]

template <class T, class U> concept bool WeaklyEqualityComparableWith = 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&&; };

Let t and u be const lvalues of types remove_reference_t<T> and remove_reference_t<U> respectively. WeaklyEqualityComparableWith<T, U> is satisfied 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 bool EqualityComparable = WeaklyEqualityComparableWith<T, T>;

Let a and b be objects of type T. EqualityComparable<T> is satisfied only if:

  • bool(a == b) if and only if a is equal to b.

Note: The requirement that the expression a == b is equality preserving implies that == is reflexive, transitive, and symmetric. — end note ]

template <class T, class U> concept bool EqualityComparableWith = EqualityComparable<T> && EqualityComparable<U> && CommonReference< const remove_reference_t<T>&, const remove_reference_t<U>&> && EqualityComparable< common_reference_t< const remove_reference_t<T>&, const remove_reference_t<U>&>> && WeaklyEqualityComparableWith<T, U>;

Let t be a const lvalue of type remove_reference_t<T>, u be a const lvalue of type remove_reference_t<U>, and C be:

common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>

EqualityComparableWith<T, U> is satisfied only if:

  • bool(t == u) == bool(C(t) == C(u)).

7.4.4 Concept StrictTotallyOrdered [concepts.lib.compare.stricttotallyordered]

template <class T> concept bool StrictTotallyOrdered = EqualityComparable<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&&; };

Let a, b, and c be const lvalues of type remove_reference_t<T>. StrictTotallyOrdered<T> is satisfied 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 bool StrictTotallyOrderedWith = StrictTotallyOrdered<T> && StrictTotallyOrdered<U> && CommonReference< const remove_reference_t<T>&, const remove_reference_t<U>&> && StrictTotallyOrdered< common_reference_t< const remove_reference_t<T>&, const remove_reference_t<U>&>> && EqualityComparableWith<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&&; };

Let t be a const lvalue of type remove_reference_t<T>, u be a const lvalue of type remove_reference_t<U>, and C be:

common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>

StrictTotallyOrderedWith<T, U> is satisfied 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)).