Files
2025-10-25 03:02:53 +03:00

20 KiB
Raw Permalink Blame History

[concepts.compare]

18 Concepts library [concepts]

18.5 Comparison concepts [concepts.compare]

18.5.1 General [concepts.compare.general]

1

#

Subclause [concepts.compare] describes concepts that establish relationships and orderings on values of possibly differing object types.

2

#

Given an expression E and a type C, let CONVERT_TO_LVALUE(E) be:

static_cast<const C&>(as_const(E)) if that is a valid expression, and

static_cast<const C&>(std::move(E)) otherwise.

18.5.2 Boolean testability [concept.booleantestable]

1

#

The exposition-only boolean-testable concept specifies the requirements on expressions that are convertible to bool and for which the logical operators ([expr.log.and], [expr.log.or], [expr.unary.op]) have the conventional semantics.

🔗

template<class T> concept [boolean-testable-impl](#concept:boolean-testable-impl "18.5.2Boolean testability[concept.booleantestable]") = [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<T, bool>; // exposition only

2

#

Let e be an expression such thatdecltype((e)) is T.

T models boolean-testable-impl only if

either remove_cvref_t is not a class type, or a search for the names operator&& and operator|| in the scope of remove_cvref_t finds nothing; and

argument-dependent lookup ([basic.lookup.argdep]) for the names operator&& and operator|| with T as the only argument type finds no disqualifying declaration (defined below).

3

#

A disqualifying parameter is a function parameter whose declared type P

is not dependent on a template parameter, and there exists an implicit conversion sequence ([over.best.ics]) from e to P; or

is dependent on one or more template parameters, and either

P contains no template parameter that participates in template argument deduction ([temp.deduct.type]), or

template argument deduction using the rules for deducing template arguments in a function call ([temp.deduct.call]) ande as the argument succeeds.

4

#

A key parameter of a function template D is a function parameter of type cv X or reference thereto, where X names a specialization of a class template that has the same innermost enclosing non-inline namespace as D, andX contains at least one template parameter that participates in template argument deduction.

[Example 1:

Innamespace Z {template struct C {}; templatevoid operator&&(C x, T y); templatevoid operator||(C<type_identity_t> x, T y);} the declaration of Z::operator&& contains one key parameter, C x, and the declaration of Z::operator|| contains no key parameters.

— end example]

5

#

A disqualifying declaration is

a (non-template) function declaration that contains at least one disqualifying parameter; or

a function template declaration that contains at least one disqualifying parameter, where

at least one disqualifying parameter is a key parameter; or

the declaration contains no key parameters; or

the declaration declares a function template to which no name is bound ([dcl.meaning]).

6

#

[Note 1:

The intention is to ensure that given two types T1 and T2 that each model boolean-testable-impl, the && and || operators within the expressionsdeclval() && declval() anddeclval() || declval() resolve to the corresponding built-in operators.

— end note]

🔗

template<class T> concept [boolean-testable](#concept:boolean-testable "18.5.2Boolean testability[concept.booleantestable]") = // exposition only [boolean-testable-impl](#concept:boolean-testable-impl "18.5.2Boolean testability[concept.booleantestable]")<T> && requires(T&& t) { { !std::forward<T>(t) } -> [boolean-testable-impl](#concept:boolean-testable-impl "18.5.2Boolean testability[concept.booleantestable]"); };

7

#

Let e be an expression such thatdecltype((e)) is T.

T models boolean-testable only ifbool(e) == !bool(!e).

8

#

[Example 2:

The typesbool,true_type ([meta.type.synop]),int*, andbitset::reference ([template.bitset]) model boolean-testable.

— end example]

18.5.3 Comparison common types [concept.comparisoncommontype]

🔗

`template<class T, class U, class C = common_reference_t<const T&, const U&>> concept comparison-common-type-with-impl = // exposition only same_as<common_reference_t<const T&, const U&>, common_reference_t<const U&, const T&>> && requires { requires convertible_to<const T&, const C&> || convertible_to<T, const C&>; requires convertible_to<const U&, const C&> || convertible_to<U, const C&>; };

template<class T, class U> concept comparison-common-type-with = // exposition only comparison-common-type-with-impl<remove_cvref_t, remove_cvref_t>; `

1

#

Let C be common_reference_t<const T&, const U&>.

Let t1 and t2 be equality-preserving expressions that are lvalues of type remove_cvref_t, and let u1 and u2 be equality-preserving expressions that are lvalues of type remove_cvref_t.

T and U modelcomparison-common-type-with<T, U> only if

CONVERT_TO_LVALUE(t1) equalsCONVERT_TO_LVALUE(t2) if and only if t1 equals t2, and

CONVERT_TO_LVALUE(u1) equalsCONVERT_TO_LVALUE(u2) if and only if u1 equals u2

18.5.4 Concept equality_comparable [concept.equalitycomparable]

🔗

template<class T, class U> concept [weakly-equality-comparable-with](#concept:weakly-equality-comparable-with "18.5.4Concept equality_­comparable[concept.equalitycomparable]") = // exposition only requires(const remove_reference_t<T>& t, const remove_reference_t<U>& u) { { t == u } -> [boolean-testable](#concept:boolean-testable "18.5.2Boolean testability[concept.booleantestable]"); { t != u } -> [boolean-testable](#concept:boolean-testable "18.5.2Boolean testability[concept.booleantestable]"); { u == t } -> [boolean-testable](#concept:boolean-testable "18.5.2Boolean testability[concept.booleantestable]"); { u != t } -> [boolean-testable](#concept:boolean-testable "18.5.2Boolean testability[concept.booleantestable]"); };

1

#

Given types T and U, let t and u be lvalues of typesconst remove_reference_t andconst remove_reference_t respectively.

T and U modelweakly-equality-comparable-with<T, U> only if

  • (1.1)

    t == u, u == t, t != u, and u != t have the same domain.

  • (1.2)

    bool(u == t) == bool(t == u).

  • (1.3)

    bool(t != u) == !bool(t == u).

  • (1.4)

    bool(u != t) == bool(t != u).

🔗

template<class T> concept [equality_comparable](#concept:equality_comparable "18.5.4Concept equality_­comparable[concept.equalitycomparable]") = [weakly-equality-comparable-with](#concept:weakly-equality-comparable-with "18.5.4Concept equality_­comparable[concept.equalitycomparable]")<T, T>;

2

#

Let a and b be objects of type T.

T models equality_comparable only ifbool(a == b) is true when a is equal tob ([concepts.equality]), and false otherwise.

3

#

[Note 1:

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](#concept:equality_comparable_with "18.5.4Concept equality_­comparable[concept.equalitycomparable]") = [equality_comparable](#concept:equality_comparable "18.5.4Concept equality_­comparable[concept.equalitycomparable]")<T> && [equality_comparable](#concept:equality_comparable "18.5.4Concept equality_­comparable[concept.equalitycomparable]")<U> && [comparison-common-type-with](#concept:comparison-common-type-with "18.5.3Comparison common types[concept.comparisoncommontype]")<T, U> && [equality_comparable](#concept:equality_comparable "18.5.4Concept equality_­comparable[concept.equalitycomparable]")< common_reference_t< const remove_reference_t<T>&, const remove_reference_t<U>&>> && [weakly-equality-comparable-with](#concept:weakly-equality-comparable-with "18.5.4Concept equality_­comparable[concept.equalitycomparable]")<T, U>;

4

#

Given types T and U, let t and t2 be lvalues denoting distinct equal objects of types const remove_reference_t andremove_cvref_t, respectively, let u and u2 be lvalues denoting distinct equal objects of types const remove_reference_t andremove_cvref_t, respectively, and let C be:common_reference_t<const remove_reference_t&, const remove_reference_t&>T and U modelequality_comparable_with<T, U> only ifbool(t == u) == bool(CONVERT_TO_LVALUE(t2) == CONVERT_TO_LVALUE(u2))

18.5.5 Concept totally_ordered [concept.totallyordered]

🔗

template<class T> concept [totally_ordered](#concept:totally_ordered "18.5.5Concept totally_­ordered[concept.totallyordered]") = [equality_comparable](#concept:equality_comparable "18.5.4Concept equality_­comparable[concept.equalitycomparable]")<T> && [partially-ordered-with](cmp.concept#concept:partially-ordered-with "17.12.4Concept three_­way_­comparable[cmp.concept]")<T, T>;

1

#

Given a type T, let a, b, and c be lvalues of type const remove_reference_t.

T models totally_ordered only if

  • (1.1)

    Exactly one of bool(a < b), bool(a > b), or bool(a == b) is true.

  • (1.2)

    If bool(a < b) and bool(b < c), then bool(a < c).

  • (1.3)

    bool(a <= b) == !bool(b < a).

  • (1.4)

    bool(a >= b) == !bool(a < b).

🔗

template<class T, class U> concept [totally_ordered_with](#concept:totally_ordered_with "18.5.5Concept totally_­ordered[concept.totallyordered]") = [totally_ordered](#concept:totally_ordered "18.5.5Concept totally_­ordered[concept.totallyordered]")<T> && [totally_ordered](#concept:totally_ordered "18.5.5Concept totally_­ordered[concept.totallyordered]")<U> && [equality_comparable_with](#concept:equality_comparable_with "18.5.4Concept equality_­comparable[concept.equalitycomparable]")<T, U> && [totally_ordered](#concept:totally_ordered "18.5.5Concept totally_­ordered[concept.totallyordered]")< common_reference_t< const remove_reference_t<T>&, const remove_reference_t<U>&>> && [partially-ordered-with](cmp.concept#concept:partially-ordered-with "17.12.4Concept three_­way_­comparable[cmp.concept]")<T, U>;

2

#

Given types T and U, let t and t2 be lvalues denoting distinct equal objects of types const remove_reference_t andremove_cvref_t, respectively, let u and u2 be lvalues denoting distinct equal objects of types const remove_reference_t andremove_cvref_t, respectively, and let C be:common_reference_t<const remove_reference_t&, const remove_reference_t&>T and U modeltotally_ordered_with<T, U> only if

  • (2.1)

    bool(t < u) == bool(CONVERT_TO_LVALUE(t2) < CONVERT_TO_LVALUE(u2)).

  • (2.2)

    bool(t > u) == bool(CONVERT_TO_LVALUE(t2) > CONVERT_TO_LVALUE(u2)).

  • (2.3)

    bool(t <= u) == bool(CONVERT_TO_LVALUE(t2) <= CONVERT_TO_LVALUE(u2)).

  • (2.4)

    bool(t >= u) == bool(CONVERT_TO_LVALUE(t2) >= CONVERT_TO_LVALUE(u2)).

  • (2.5)

    bool(u < t) == bool(CONVERT_TO_LVALUE(u2) < CONVERT_TO_LVALUE(t2)).

  • (2.6)

    bool(u > t) == bool(CONVERT_TO_LVALUE(u2) > CONVERT_TO_LVALUE(t2)).

  • (2.7)

    bool(u <= t) == bool(CONVERT_TO_LVALUE(u2) <= CONVERT_TO_LVALUE(t2)).

  • (2.8)

    bool(u >= t) == bool(CONVERT_TO_LVALUE(u2) >= CONVERT_TO_LVALUE(t2)).