[concepts] (original) (raw)

18 Concepts library [concepts]

18.1 General [concepts.general]

This Clause describes library components that C++ programs may use to perform compile-time validation of template arguments and perform function dispatch based on properties of types.

The purpose of these concepts is to establish a foundation for equational reasoning in programs.

The following subclauses describe language-related concepts, comparison concepts, object concepts, and callable concepts as summarized in Table 48.

Table 48 — Fundamental concepts library summary [tab:concepts.summary]

🔗 Subclause Header
🔗[concepts.equality] Equality preservation
🔗[concepts.lang] Language-related concepts <concepts>
🔗[concepts.compare] Comparison concepts
🔗[concepts.object] Object concepts
🔗[concepts.callable] Callable concepts

18.2 Equality preservation [concepts.equality]

An expression is equality-preserving if, given equal inputs, the expression results in equal outputs.

The inputs to an expression are the set of the expression's operands.

The output of an expression is the expression's result and all operands modified by the expression.

For the purposes of this subclause, the operands of an expression are the largest subexpressions that include only:

[Example 1:

The operands of the expression a = std​::​move(b) area and std​::​move(b).

— _end example_]

Not all input values need be valid for a given expression.

[Example 2:

For integers a and b, the expression a / b is not well-defined when b is 0.

This does not preclude the expression a / b being equality-preserving.

— _end example_]

The domain of an expression is the set of input values for which the expression is required to be well-defined.

Expressions required to be equality-preserving are further required to be stable: two evaluations of such an expression with the same input objects are required to have equal outputs absent any explicit intervening modification of those input objects.

[Note 1:

This requirement allows generic code to reason about the current values of objects based on knowledge of the prior values as observed via equality-preserving expressions.

It effectively forbids spontaneous changes to an object, changes to an object from another thread of execution, changes to an object as side effects of non-modifying expressions, and changes to an object as side effects of modifying a distinct object if those changes could be observable to a library function via an equality-preserving expression that is required to be valid for that object.

— _end note_]

Expressions declared in a requires-expression in the library clauses are required to be equality-preserving, except for those annotated with the comment “not required to be equality-preserving.

An expression so annotated may be equality-preserving, but is not required to be so.

An expression that may alter the value of one or more of its inputs in a manner observable to equality-preserving expressions is said to modify those inputs.

The library clauses use a notational convention to specify which expressions declared in a requires-expression modify which inputs: except where otherwise specified, an expression operand that is a non-constant lvalue or rvalue may be modified.

Operands that are constant lvalues or rvalues are required to not be modified.

For the purposes of this subclause, the cv-qualification and value category of each operand are determined by assuming that each template type parameter denotes a cv-unqualified complete non-array object type.

Where a requires-expression declares an expression that is non-modifying for some constant lvalue operand, additional variations of that expression that accept a non-constant lvalue or (possibly constant) rvalue for the given operand are also required except where such an expression variation is explicitly required with differing semantics.

Theseimplicit expression variations are required to meet the semantic requirements of the declared expression.

The extent to which an implementation validates the syntax of the variations is unspecified.

[Example 3: template<class T> concept C = requires(T a, T b, const T c, const T d) { c == d; a = std::move(b); a = c; };

For the above example:

— _end example_]

[Example 4:

The following type T meets the explicitly stated syntactic requirements of concept C above but does not meet the additional implicit requirements:struct T { bool operator==(const T&) const { return true; } bool operator==(T&) = delete;};

T fails to meet the implicit requirements of C, so T satisfies but does not model C.

Since implementations are not required to validate the syntax of implicit requirements, it is unspecified whether an implementation diagnoses as ill-formed a program that requires C<T>.

— _end example_]

18.4.1 General [concepts.lang.general]

Subclause [concepts.lang] contains the definition of concepts corresponding to language features.

These concepts express relationships between types, type classifications, and fundamental type properties.

18.4.2 Concept same_as [concept.same]

template<class T, class U> concept [_same-as-impl_](#concept:same-as-impl "18.4.2 Concept same_­as [concept.same]") = [is_same_v](meta.type.synop#lib:is%5Fsame%5Fv "21.3.3 Header <type_­traits> synopsis [meta.type.synop]")<T, U>; // _exposition only_ template<class T, class U> concept [same_as](#concept:same%5Fas "18.4.2 Concept same_­as [concept.same]") = [_same-as-impl_](#concept:same-as-impl "18.4.2 Concept same_­as [concept.same]")<T, U> && [_same-as-impl_](#concept:same-as-impl "18.4.2 Concept same_­as [concept.same]")<U, T>;

[Note 1:

same_as<T, U> subsumes same_as<U, T> and vice versa.

— _end note_]

18.4.3 Concept derived_from [concept.derived]

template<class Derived, class Base> concept [derived_from](#concept:derived%5Ffrom "18.4.3 Concept derived_­from [concept.derived]") = is_base_of_v<Base, Derived> && is_convertible_v<const volatile Derived*, const volatile Base*>;

[Note 1:

derived_from<Derived, Base> is satisfied if and only ifDerived is publicly and unambiguously derived from Base, orDerived and Base are the same class type ignoring cv-qualifiers.

— _end note_]

18.4.4 Concept convertible_to [concept.convertible]

Given types From and To and an expression Ewhose type and value category are the same as those of declval<From>(),convertible_to<From, To> requires Eto be both implicitly and explicitly convertible to type To.

The implicit and explicit conversions are required to produce equal results.

template<class From, class To> concept [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]") = is_convertible_v<From, To> && requires { static_cast<To>(declval<From>());};

Let FromR be add_rvalue_reference_t<From> andtest be the invented function:To test(FromR (&f)()) { return f();} and let f be a function with no arguments and return type FromRsuch that f() is equality-preserving.

Types From and To model convertible_to<From, To>only if:

18.4.5 Concept common_reference_with [concept.commonref]

For two types T and U, if common_reference_t<T, U>is well-formed and denotes a type C such that bothconvertible_to<T, C>andconvertible_to<U, C>are modeled, then T and U share acommon reference type, C.

[Note 1:

C can be the same as T or U, or can be a different type.

C can be a reference type.

— _end note_]

template<class T, class U> concept [common_reference_with](#concept:common%5Freference%5Fwith "18.4.5 Concept common_­reference_­with [concept.commonref]") = [same_as](#concept:same%5Fas "18.4.2 Concept same_­as [concept.same]")<common_reference_t<T, U>, common_reference_t<U, T>> && [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<T, common_reference_t<T, U>> && [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<U, common_reference_t<T, U>>;

Let C be common_reference_t<T, U>.

Let t1 and t2 be equality-preserving expressions ([concepts.equality]) such thatdecltype((t1)) and decltype((t2)) are each T, and let u1 and u2 be equality-preserving expressions such thatdecltype((u1)) and decltype((u2)) are each U.

T and U model common_reference_with<T, U>only if

[Note 2:

Users can customize the behavior of common_reference_with by specializing the basic_common_reference class template ([meta.trans.other]).

— _end note_]

18.4.6 Concept common_with [concept.common]

If T and U can both be explicitly converted to some third type,C, then T and U share a common type,C.

[Note 1:

C can be the same as T or U, or can be a different type.

C is not necessarily unique.

— _end note_]

template<class T, class U> concept [common_with](#concept:common%5Fwith "18.4.6 Concept common_­with [concept.common]") = [same_as](#concept:same%5Fas "18.4.2 Concept same_­as [concept.same]")<common_type_t<T, U>, common_type_t<U, T>> && requires { static_cast<common_type_t<T, U>>(declval<T>());static_cast<common_type_t<T, U>>(declval<U>());} && [common_reference_with](#concept:common%5Freference%5Fwith "18.4.5 Concept common_­reference_­with [concept.commonref]")< add_lvalue_reference_t<const T>, add_lvalue_reference_t<const U>> && [common_reference_with](#concept:common%5Freference%5Fwith "18.4.5 Concept common_­reference_­with [concept.commonref]")< add_lvalue_reference_t<common_type_t<T, U>>, common_reference_t< add_lvalue_reference_t<const T>, add_lvalue_reference_t<const U>>>;

Let C be common_type_t<T, U>.

Let t1 and t2 be equality-preserving expressions ([concepts.equality]) such thatdecltype((t1)) and decltype((t2)) are each T, and let u1 and u2 be equality-preserving expressions such thatdecltype((u1)) and decltype((u2)) are each U.

T and U model common_with<T, U>only if

[Note 2:

Users can customize the behavior of common_with by specializing thecommon_type class template ([meta.trans.other]).

— _end note_]

18.4.7 Arithmetic concepts [concepts.arithmetic]

template<class T> concept [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [is_integral_v](meta.type.synop#lib:is%5Fintegral%5Fv "21.3.3 Header <type_­traits> synopsis [meta.type.synop]")<T>;template<class T> concept [signed_integral](#concept:signed%5Fintegral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]")<T> && [is_signed_v](meta.type.synop#lib:is%5Fsigned%5Fv "21.3.3 Header <type_­traits> synopsis [meta.type.synop]")<T>;template<class T> concept [unsigned_integral](#concept:unsigned%5Fintegral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]")<T> && ![signed_integral](#concept:signed%5Fintegral "18.4.7 Arithmetic concepts [concepts.arithmetic]")<T>;template<class T> concept [floating_point](#concept:floating%5Fpoint "18.4.7 Arithmetic concepts [concepts.arithmetic]") = is_floating_point_v<T>;

[Note 1:

signed_integral can be modeled even by types that are not signed integer types ([basic.fundamental]); for example, char.

— _end note_]

[Note 2:

unsigned_integral can be modeled even by types that are not unsigned integer types ([basic.fundamental]); for example, bool.

— _end note_]

18.4.8 Concept assignable_from [concept.assignable]

template<class LHS, class RHS> concept [assignable_from](#concept:assignable%5Ffrom "18.4.8 Concept assignable_­from [concept.assignable]") = is_lvalue_reference_v<LHS> && [common_reference_with](#concept:common%5Freference%5Fwith "18.4.5 Concept common_­reference_­with [concept.commonref]")<const remove_reference_t<LHS>&, const remove_reference_t<RHS>&> && requires(LHS lhs, RHS&& rhs) { { lhs = std::forward<RHS>(rhs) } -> [same_as](#concept:same%5Fas "18.4.2 Concept same_­as [concept.same]")<LHS>;};

Let:

LHS and RHS modelassignable_from<LHS, RHS> only if

[Note 1:

Assignment need not be a total function ([structure.requirements]); in particular, if assignment to an object x can result in a modification of some other object y, then x = y is likely not in the domain of =.

— _end note_]

18.4.9 Concept swappable [concept.swappable]

Let t1 and t2 be equality-preserving expressions that denote distinct equal objects of type T, and let u1 and u2similarly denote distinct equal objects of type U.

[Note 1:

t1 and u1 can denote distinct objects, or the same object.

— _end note_]

An operationexchanges the values denoted by t1 and u1 if and only if the operation modifies neither t2 nor u2 and:

The expressionranges​::​swap(E1, E2) for subexpressions E1and E2 is expression-equivalent to an expressionS determined as follows:

[Note 4:

Whenever ranges​::​swap(E1, E2) is a valid expression, it exchanges the values denoted byE1 and E2 and has type void.

— _end note_]

template<class T> concept [swappable](#concept:swappable "18.4.9 Concept swappable [concept.swappable]") = requires(T& a, T& b) { ranges::swap(a, b); };

template<class T, class U> concept [swappable_with](#concept:swappable%5Fwith "18.4.9 Concept swappable [concept.swappable]") = [common_reference_with](#concept:common%5Freference%5Fwith "18.4.5 Concept common_­reference_­with [concept.commonref]")<T, U> && requires(T&& t, U&& u) { ranges::swap(std::forward<T>(t), std::forward<T>(t)); ranges::swap(std::forward<U>(u), std::forward<U>(u)); ranges::swap(std::forward<T>(t), std::forward<U>(u)); ranges::swap(std::forward<U>(u), std::forward<T>(t));};

[Note 5:

The semantics of the swappable and swappable_withconcepts are fully defined by the ranges​::​swap customization point object.

— _end note_]

[Example 1:

User code can ensure that the evaluation of swap calls is performed in an appropriate context under the various conditions as follows:#include <cassert> #include <concepts> #include <utility> namespace ranges = std::ranges;template<class T, std::swappable_with<T> U> void value_swap(T&& t, U&& u) { ranges::swap(std::forward<T>(t), std::forward<U>(u));} template<std::swappable T> void lv_swap(T& t1, T& t2) { ranges::swap(t1, t2);} namespace N { struct A { int m; };struct Proxy { A* a; Proxy(A& a) : a{&a} {} friend void swap(Proxy x, Proxy y) { ranges::swap(*x.a, *y.a);} }; Proxy proxy(A& a) { return Proxy{ a }; } } int main() { int i = 1, j = 2; lv_swap(i, j); assert(i == 2 && j == 1); N::A a1 = { 5 }, a2 = { -5 }; value_swap(a1, proxy(a2)); assert(a1.m == -5 && a2.m == 5);}

— _end example_]

18.4.10 Concept destructible [concept.destructible]

The destructible concept specifies properties of all types, instances of which can be destroyed at the end of their lifetime, or reference types.

[Note 1:

Unlike the Cpp17Destructible requirements (Table 35), this concept forbids destructors that are potentially throwing, even if a particular invocation of the destructor does not actually throw.

— _end note_]

18.4.11 Concept constructible_from [concept.constructible]

The constructible_from concept constrains the initialization of a variable of a given type with a particular set of argument types.

18.4.12 Concept default_initializable [concept.default.init]

template<class T> constexpr bool _is-default-initializable_ = _see below_; // _exposition only_ template<class T> concept [default_initializable](#concept:default%5Finitializable "18.4.12 Concept default_­initializable [concept.default.init]") = [constructible_from](#concept:constructible%5Ffrom "18.4.11 Concept constructible_­from [concept.constructible]")<T> && requires { T{}; } && _is-default-initializable_<T>;

For a type T, is-default-initializable<T> is trueif and only if the variable definitionT t;is well-formed for some invented variable t; otherwise it is false.

Access checking is performed as if in a context unrelated to T.

Only the validity of the immediate context of the variable initialization is considered.

18.4.13 Concept move_constructible [concept.moveconstructible]

template<class T> concept [move_constructible](#concept:move%5Fconstructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") = [constructible_from](#concept:constructible%5Ffrom "18.4.11 Concept constructible_­from [concept.constructible]")<T, T> && [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<T, T>;

If T is an object type, then let rv be an rvalue of typeT and u2 a distinct object of type T equal torv.

T models move_constructible only if

18.4.14 Concept copy_constructible [concept.copyconstructible]

template<class T> concept [copy_constructible](#concept:copy%5Fconstructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") = [move_constructible](#concept:move%5Fconstructible "18.4.13 Concept move_­constructible [concept.moveconstructible]")<T> && [constructible_from](#concept:constructible%5Ffrom "18.4.11 Concept constructible_­from [concept.constructible]")<T, T&> && [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<T&, T> && [constructible_from](#concept:constructible%5Ffrom "18.4.11 Concept constructible_­from [concept.constructible]")<T, const T&> && [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const T&, T> && [constructible_from](#concept:constructible%5Ffrom "18.4.11 Concept constructible_­from [concept.constructible]")<T, const T> && [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const T, T>;

If T is an object type, then let v be an lvalue of typeT or const T or an rvalue of type const T.

T models copy_constructible only if

18.5 Comparison concepts [concepts.compare]

18.5.1 General [concepts.compare.general]

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

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

18.5.2 Boolean testability [concept.booleantestable]

template<class T> concept [_boolean-testable-impl_](#concept:boolean-testable-impl "18.5.2 Boolean testability [concept.booleantestable]") = [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<T, bool>; // _exposition only_

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

T models boolean-testable-impl only if

A disqualifying parameteris a function parameter whose declared type P

A key parameter of a function template Dis 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<class> struct C {};template<class T> void operator&&(C<T> x, T y);template<class T> void operator||(C<type_identity_t<T>> x, T y);} the declaration of Z​::​operator&&contains one key parameter, C<T> x, and the declaration of Z​::​operator||contains no key parameters.

— _end example_]

A disqualifying declaration is

[Note 1:

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

— _end note_]

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

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

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

[Example 2:

— _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_](#concept:comparison-common-type-with-impl "18.5.3 Comparison common types [concept.comparisoncommontype]") = // _exposition only_ [same_as](#concept:same%5Fas "18.4.2 Concept same_­as [concept.same]")<common_reference_t<const T&, const U&>, common_reference_t<const U&, const T&>> && requires { requires [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const T&, const C&> || [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<T, const C&>;requires [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const U&, const C&> || [convertible_to](#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<U, const C&>;};template<class T, class U> concept [_comparison-common-type-with_](#concept:comparison-common-type-with "18.5.3 Comparison common types [concept.comparisoncommontype]") = // _exposition only_ [_comparison-common-type-with-impl_](#concept:comparison-common-type-with-impl "18.5.3 Comparison common types [concept.comparisoncommontype]")<remove_cvref_t<T>, remove_cvref_t<U>>;

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<T>, and let u1 and u2 be equality-preserving expressions that are lvalues of type remove_cvref_t<U>.

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

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.4 Concept 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.2 Boolean testability [concept.booleantestable]");{ t != u } -> [_boolean-testable_](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]");{ u == t } -> [_boolean-testable_](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]");{ u != t } -> [_boolean-testable_](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]");};

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

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

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

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.

[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%5Fcomparable%5Fwith "18.5.4 Concept equality_­comparable [concept.equalitycomparable]") = [equality_comparable](#concept:equality%5Fcomparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<T> && [equality_comparable](#concept:equality%5Fcomparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<U> && [_comparison-common-type-with_](#concept:comparison-common-type-with "18.5.3 Comparison common types [concept.comparisoncommontype]")<T, U> && [equality_comparable](#concept:equality%5Fcomparable "18.5.4 Concept 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.4 Concept equality_­comparable [concept.equalitycomparable]")<T, U>;

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

18.5.5 Concept totally_ordered [concept.totallyordered]

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

T models totally_ordered only if

template<class T, class U> concept [totally_ordered_with](#concept:totally%5Fordered%5Fwith "18.5.5 Concept totally_­ordered [concept.totallyordered]") = [totally_ordered](#concept:totally%5Fordered "18.5.5 Concept totally_­ordered [concept.totallyordered]")<T> && [totally_ordered](#concept:totally%5Fordered "18.5.5 Concept totally_­ordered [concept.totallyordered]")<U> && [equality_comparable_with](#concept:equality%5Fcomparable%5Fwith "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<T, U> && [totally_ordered](#concept:totally%5Fordered "18.5.5 Concept 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.4 Concept three_­way_­comparable [cmp.concept]")<T, U>;

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

18.6 Object concepts [concepts.object]

This subclause describes concepts that specify the basis of the value-oriented programming style on which the library is based.

template<class T> concept [movable](#concept:movable "18.6 Object concepts [concepts.object]") = is_object_v<T> && [move_constructible](#concept:move%5Fconstructible "18.4.13 Concept move_­constructible [concept.moveconstructible]")<T> && [assignable_from](#concept:assignable%5Ffrom "18.4.8 Concept assignable_­from [concept.assignable]")<T&, T> && [swappable](#concept:swappable "18.4.9 Concept swappable [concept.swappable]")<T>;template<class T> concept [copyable](#concept:copyable "18.6 Object concepts [concepts.object]") = [copy_constructible](#concept:copy%5Fconstructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<T> && [movable](#concept:movable "18.6 Object concepts [concepts.object]")<T> && [assignable_from](#concept:assignable%5Ffrom "18.4.8 Concept assignable_­from [concept.assignable]")<T&, T&> && [assignable_from](#concept:assignable%5Ffrom "18.4.8 Concept assignable_­from [concept.assignable]")<T&, const T&> && [assignable_from](#concept:assignable%5Ffrom "18.4.8 Concept assignable_­from [concept.assignable]")<T&, const T>;template<class T> concept [semiregular](#concept:semiregular "18.6 Object concepts [concepts.object]") = [copyable](#concept:copyable "18.6 Object concepts [concepts.object]")<T> && [default_initializable](#concept:default%5Finitializable "18.4.12 Concept default_­initializable [concept.default.init]")<T>;template<class T> concept [regular](#concept:regular "18.6 Object concepts [concepts.object]") = [semiregular](#concept:semiregular "18.6 Object concepts [concepts.object]")<T> && [equality_comparable](#concept:equality%5Fcomparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<T>;

[Note 1:

The semiregular concept is modeled by types that behave similarly to fundamental types like int, except that they need not be comparable with ==.

— _end note_]

[Note 2:

The regular concept is modeled by types that behave similarly to fundamental types like int and that are comparable with==.

— _end note_]

18.7 Callable concepts [concepts.callable]

18.7.2 Concept invocable [concept.invocable]

The invocable concept specifies a relationship between a callable type ([func.def]) F and a set of argument types Args... which can be evaluated by the library function invoke ([func.invoke]).

template<class F, class... Args> concept [invocable](#concept:invocable "18.7.2 Concept invocable [concept.invocable]") = requires(F&& f, Args&&... args) { invoke(std::forward<F>(f), std::forward<Args>(args)...); // not required to be equality-preserving };

[Example 1:

A function that generates random numbers can model invocable, since the invoke function call expression is not required to be equality-preserving ([concepts.equality]).

— _end example_]

18.7.3 Concept regular_invocable [concept.regularinvocable]

template<class F, class... Args> concept [regular_invocable](#concept:regular%5Finvocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]") = [invocable](#concept:invocable "18.7.2 Concept invocable [concept.invocable]")<F, Args...>;

The invoke function call expression shall be equality-preserving ([concepts.equality]) and shall not modify the function object or the arguments.

[Note 1:

This requirement supersedes the annotation in the definition ofinvocable.

— _end note_]

[Example 1:

A random number generator does not model regular_invocable.

— _end example_]

[Note 2:

The distinction between invocable and regular_invocableis purely semantic.

— _end note_]

18.7.4 Concept predicate [concept.predicate]

template<class F, class... Args> concept [predicate](#concept:predicate "18.7.4 Concept predicate [concept.predicate]") = [regular_invocable](#concept:regular%5Finvocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<F, Args...> && [_boolean-testable_](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]")<invoke_result_t<F, Args...>>;

18.7.5 Concept relation [concept.relation]

template<class R, class T, class U> concept [relation](#concept:relation "18.7.5 Concept relation [concept.relation]") = [predicate](#concept:predicate "18.7.4 Concept predicate [concept.predicate]")<R, T, T> && [predicate](#concept:predicate "18.7.4 Concept predicate [concept.predicate]")<R, U, U> && [predicate](#concept:predicate "18.7.4 Concept predicate [concept.predicate]")<R, T, U> && [predicate](#concept:predicate "18.7.4 Concept predicate [concept.predicate]")<R, U, T>;

18.7.6 Concept equivalence_relation [concept.equiv]

template<class R, class T, class U> concept [equivalence_relation](#concept:equivalence%5Frelation "18.7.6 Concept equivalence_­relation [concept.equiv]") = [relation](#concept:relation "18.7.5 Concept relation [concept.relation]")<R, T, U>;

A relation models equivalence_relation only if it imposes an equivalence relation on its arguments.

18.7.7 Concept strict_weak_order [concept.strictweakorder]

template<class R, class T, class U> concept [strict_weak_order](#concept:strict%5Fweak%5Forder "18.7.7 Concept strict_­weak_­order [concept.strictweakorder]") = [relation](#concept:relation "18.7.5 Concept relation [concept.relation]")<R, T, U>;

A relation models strict_weak_order only if it imposes a strict weak ordering on its arguments.

The termstrictrefers to the requirement of an irreflexive relation (!comp(x, x) for all x), and the termweakto requirements that are not as strong as those for a total ordering, but stronger than those for a partial ordering.

If we defineequiv(a, b)as!comp(a, b) && !comp(b, a), then the requirements are thatcompandequivboth be transitive relations:

[Note 1:

Under these conditions, it can be shown that

— _end note_]