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.

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.

Not all input values need be valid for a given expression; e.g., 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.

Expressions required by this document 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

: *end note*

]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.

— Expressions declared in a *requires-expression* in this document 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.

This document uses 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.

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.

These
*implicit 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

: *end example*

]template<class T> concept C = requires(T a, T b, const T c, const T d) { c == d; // #1 a = std::move(b); // #2 a = c; // #3 };

For the above example:

— - Expression #1 does not modify either of its operands, #2 modifies both of its operands, and #3 modifies only its first operand a.
- Expression #1 implicitly requires additional expression variations that meet the requirements for c == d (including non-modification), as if the expressions
c == b; c == std::move(d); c == std::move(b); std::move(c) == d; std::move(c) == b; std::move(c) == std::move(d); std::move(c) == std::move(b); a == d; a == b; a == std::move(d); a == std::move(b); std::move(a) == d; std::move(a) == b; std::move(a) == std::move(d); std::move(a) == std::move(b);

had been declared as well. - Expression #3 implicitly requires additional expression variations that meet the requirements for a = c (including non-modification of the second operand), as if the expressions a = b and a = std::move(c) had been declared.Expression #3 does not implicitly require an expression variation with a non-constant rvalue second operand, since expression #2 already specifies exactly such an expression explicitly.

[ Example

: *end example*

]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; };

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>.

— namespace std { // [concepts.lang], language-related concepts // [concept.same], concept Same template<class T, class U> concept Same = see below; // [concept.derivedfrom], concept DerivedFrom template<class Derived, class Base> concept DerivedFrom = see below; // [concept.convertibleto], concept ConvertibleTo template<class From, class To> concept ConvertibleTo = see below; // [concept.commonref], concept CommonReference template<class T, class U> concept CommonReference = see below; // [concept.common], concept Common template<class T, class U> concept Common = see below; // [concepts.integral], integral concepts template<class T> concept Integral = see below; template<class T> concept SignedIntegral = see below; template<class T> concept UnsignedIntegral = see below; // [concept.assignable], concept Assignable template<class LHS, class RHS> concept Assignable = see below; // [concept.swappable], concept Swappable template<class T> concept Swappable = see below; template<class T, class U> concept SwappableWith = see below; // [concept.destructible], concept Destructible template<class T> concept Destructible = see below; // [concept.constructible], concept Constructible template<class T, class... Args> concept Constructible = see below; // [concept.defaultconstructible], concept DefaultConstructible template<class T> concept DefaultConstructible = see below; // [concept.moveconstructible], concept MoveConstructible template<class T> concept MoveConstructible = see below; // [concept.copyconstructible], concept CopyConstructible template<class T> concept CopyConstructible = see below; // [concepts.compare], comparison concepts // [concept.boolean], concept Boolean template<class B> concept Boolean = see below; // [concept.equalitycomparable], concept EqualityComparable template<class T> concept EqualityComparable = see below; template<class T, class U> concept EqualityComparableWith = see below; // [concept.stricttotallyordered], concept StrictTotallyOrdered template<class T> concept StrictTotallyOrdered = see below; template<class T, class U> concept StrictTotallyOrderedWith = see below; // [concepts.object], object concepts template<class T> concept Movable = see below; template<class T> concept Copyable = see below; template<class T> concept Semiregular = see below; template<class T> concept Regular = see below; // [concepts.callable], callable concepts // [concept.invocable], concept Invocable template<class F, class... Args> concept Invocable = see below; // [concept.regularinvocable], concept RegularInvocable template<class F, class... Args> concept RegularInvocable = see below; // [concept.predicate], concept Predicate template<class F, class... Args> concept Predicate = see below; // [concept.relation], concept Relation template<class R, class T, class U> concept Relation = see below; // [concept.strictweakorder], concept StrictWeakOrder template<class R, class T, class U> concept StrictWeakOrder = see below; }

```
template<class Derived, class Base>
concept DerivedFrom =
is_base_of_v<Base, Derived> &&
is_convertible_v<const volatile Derived*, const volatile Base*>;
```

The ConvertibleTo concept requires an expression of a particular
type and value category to be both implicitly and explicitly convertible to some
other type.

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

```
template<class From, class To>
concept ConvertibleTo =
is_convertible_v<From, To> &&
requires(From (&f)()) {
static_cast<To>(f());
};
```

Let test be the invented function:

To test(From (&f)()) { return f(); }and let f be a function with no arguments and return type From such that f() is equality-preserving.

ConvertibleTo<From, To> is satisfied only if:

- From is not a reference-to-object type, or
- If From is an rvalue reference to a non const-qualified type, the resulting state of the object referenced by f() after either above expression is valid but unspecified ([lib.types.movedfrom]).
- Otherwise, the object referred to by f() is not modified by either above expression.

For two types T and U, if common_reference_t<T, U>
is well-formed and denotes a type C such that both
ConvertibleTo<T, C>
and
ConvertibleTo<U, C>
are satisfied, then T and U share a
*common reference type*, C.

```
template<class T, class U>
concept CommonReference =
Same<common_reference_t<T, U>, common_reference_t<U, T>> &&
ConvertibleTo<T, common_reference_t<T, U>> &&
ConvertibleTo<U, common_reference_t<T, U>>;
```

CommonReference<T, U> is
satisfied only if:

[ Note

: *end note*

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

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

```
template<class T, class U>
concept Common =
Same<common_type_t<T, U>, common_type_t<U, T>> &&
ConvertibleTo<T, common_type_t<T, U>> &&
ConvertibleTo<U, common_type_t<T, U>> &&
CommonReference<
add_lvalue_reference_t<const T>,
add_lvalue_reference_t<const U>> &&
CommonReference<
add_lvalue_reference_t<common_type_t<T, U>>,
common_reference_t<
add_lvalue_reference_t<const T>,
add_lvalue_reference_t<const U>>>;
```

Common<T, U> is
satisfied only if:

[ Note

: *end note*

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

— ```
template<class T>
concept Integral = is_integral_v<T>;
template<class T>
concept SignedIntegral = Integral<T> && is_signed_v<T>;
template<class T>
concept UnsignedIntegral = Integral<T> && !SignedIntegral<T>;
```

[ Note

: *end note*

]SignedIntegral<T> can be satisfied even by types that are
not signed integral types ([basic.fundamental]); for example, char.

— [ Note

: *end note*

]UnsignedIntegral<T> can be satisfied even by types that are
not unsigned integral types ([basic.fundamental]); for example, bool.

— ```
template<class LHS, class RHS>
concept Assignable =
is_lvalue_reference_v<LHS> &&
CommonReference<const remove_reference_t<LHS>&, const remove_reference_t<RHS>&> &&
requires(LHS lhs, RHS&& rhs) {
lhs = std::forward<RHS>(rhs);
requires Same<decltype(lhs = std::forward<RHS>(rhs)), LHS>;
};
```

Let:

- lhs be an lvalue that refers to an object lcopy such that decltype((lhs)) is LHS,
- rhs be an expression such that decltype((rhs)) is RHS, and

Assignable<LHS, RHS> is satisfied only if

- addressof(lhs = rhs) == addressof(lcopy).
- After evaluating lhs = rhs:
- If rhs is a non-const xvalue, the resulting state of the object to which it refers is valid but unspecified ([lib.types.movedfrom]).
- Otherwise, if rhs is a glvalue, the object to which it refers is not modified.

[ Note

: *end note*

]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 =.

— ```
template<class T>
concept Swappable = is_swappable_v<T>;
```

The context in which swap(a1, b1) or swap(b1, a1) is evaluated
shall ensure that a binary non-member function named swap is selected via
overload resolution ([over.match]) on a candidate set that includes:

- the lookup set produced by argument-dependent lookup ([basic.lookup.argdep]).

```
template<class T, class U>
concept SwappableWith =
is_swappable_with_v<T, T> && is_swappable_with_v<U, U> &&
CommonReference<const remove_reference_t<T>&, const remove_reference_t<U>&> &&
is_swappable_with_v<T, U> && is_swappable_with_v<U, T>;
```

Let:

- t1 and t2 denote distinct equal objects of type remove_cvref_t<T>,
- be an expression that denotes t1 such that decltype(()) is T,
- u1 and u2 similarly denote distinct equal objects of type remove_cvref_t<U>,
- be an expression that denotes u1 such that decltype(()) is U, and
- C be
common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>

The context in which swap(, ) or swap(, )
is evaluated shall ensure that a binary non-member function named swap is
selected via overload resolution ([over.match]) on a candidate set that
includes:

- the lookup set produced by argument-dependent lookup ([basic.lookup.argdep]).

[ Example

: *end example*

]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> template<class T, std::SwappableWith<T> U> void value_swap(T&& t, U&& u) { using std::swap; swap(std::forward<T>(t), std::forward<U>(u)); // OK: uses “swappable with” conditions // for rvalues and lvalues } template<std::Swappable T> void lv_swap(T& t1, T& t2) { using std::swap; swap(t1, t2); // OK: uses swappable conditions for } // lvalues of type T namespace N { struct A { int m; }; struct Proxy { A* a; }; Proxy proxy(A& a) { return Proxy{ &a }; } void swap(A& x, Proxy p) { std::swap(x.m, p.a->m); // OK: uses context equivalent to swappable // conditions for fundamental types } void swap(Proxy p, A& x) { swap(x, p); } // satisfy symmetry constraint } 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); }

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

```
template<class T>
concept Destructible = is_nothrow_destructible_v<T>;
```

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

```
template<class T, class... Args>
concept Constructible = Destructible<T> && is_constructible_v<T, Args...>;
```

```
template<class T>
concept DefaultConstructible = Constructible<T>;
```

```
template<class T>
concept MoveConstructible = Constructible<T, T> && ConvertibleTo<T, T>;
```

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

MoveConstructible<T> is satisfied only if

```
template<class T>
concept CopyConstructible =
MoveConstructible<T> &&
Constructible<T, T&> && ConvertibleTo<T&, T> &&
Constructible<T, const T&> && ConvertibleTo<const T&, T> &&
Constructible<T, const T> && ConvertibleTo<const T, T>;
```

```
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) {
requires ConvertibleTo<const remove_reference_t<B>&, bool>;
!b1; requires ConvertibleTo<decltype(!b1), bool>;
b1 && a; requires Same<decltype(b1 && a), bool>;
b1 || a; requires Same<decltype(b1 || a), bool>;
b1 && b2; requires Same<decltype(b1 && b2), bool>;
a && b2; requires Same<decltype( a && b2), bool>;
b1 || b2; requires Same<decltype(b1 || b2), bool>;
a || b2; requires Same<decltype( a || b2), bool>;
b1 == b2; requires ConvertibleTo<decltype(b1 == b2), bool>;
b1 == a; requires ConvertibleTo<decltype(b1 == a), bool>;
a == b2; requires ConvertibleTo<decltype( a == b2), bool>;
b1 != b2; requires ConvertibleTo<decltype(b1 != b2), bool>;
b1 != a; requires ConvertibleTo<decltype(b1 != a), bool>;
a != b2; requires ConvertibleTo<decltype( a != b2), bool>;
};
```

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

: *end example*

]The types bool, true_type ([meta.type.synop]), and
bitset<N>::reference ([template.bitset]) are Boolean
types.

— ```
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; requires Boolean<decltype(t == u)>;
t != u; requires Boolean<decltype(t != u)>;
u == t; requires Boolean<decltype(u == t)>;
u != t; requires Boolean<decltype(u != t)>;
};
```

Let t and u be lvalues of types
const remove_reference_t<T> and
const remove_reference_t<U> respectively.

```
template<class T>
concept EqualityComparable = weakly-equality-comparable-with<T, T>;
```

EqualityComparable<T> is satisfied only if
bool(a == b) is true when a is equal to
b ([concepts.equality]), and false otherwise.

```
template<class T, class U>
concept 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>&>> &&
weakly-equality-comparable-with<T, U>;
```

```
template<class T>
concept StrictTotallyOrdered =
EqualityComparable<T> &&
requires(const remove_reference_t<T>& a,
const remove_reference_t<T>& b) {
a < b; requires Boolean<decltype(a < b)>;
a > b; requires Boolean<decltype(a > b)>;
a <= b; requires Boolean<decltype(a <= b)>;
a >= b; requires Boolean<decltype(a >= b)>;
};
```

StrictTotallyOrdered<T> is satisfied only if

```
template<class T, class U>
concept 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; requires Boolean<decltype(t < u)>;
t > u; requires Boolean<decltype(t > u)>;
t <= u; requires Boolean<decltype(t <= u)>;
t >= u; requires Boolean<decltype(t >= u)>;
u < t; requires Boolean<decltype(u < t)>;
u > t; requires Boolean<decltype(u > t)>;
u <= t; requires Boolean<decltype(u <= t)>;
u >= t; requires Boolean<decltype(u >= t)>;
};
```

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>&>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)).

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 = is_object_v<T> && MoveConstructible<T> && Assignable<T&, T> && Swappable<T>;
template<class T>
concept Copyable = CopyConstructible<T> && Movable<T> && Assignable<T&, const T&>;
template<class T>
concept Semiregular = Copyable<T> && DefaultConstructible<T>;
template<class T>
concept Regular = Semiregular<T> && EqualityComparable<T>;
```

The concepts in this subclause describe the requirements on function
objects ([function.objects]) and their arguments.

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 = requires(F&& f, Args&&... args) {
invoke(std::forward<F>(f), std::forward<Args>(args)...); // not required to be equality-preserving
};
```

[ Example

: *end example*

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

— ```
template<class F, class... Args>
concept RegularInvocable = Invocable<F, Args...>;
```

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

```
template<class F, class... Args>
concept Predicate = RegularInvocable<F, Args...> && Boolean<invoke_result_t<F, Args...>>;
```

```
template<class R, class T, class U>
concept Relation =
Predicate<R, T, T> && Predicate<R, U, U> &&
CommonReference<const remove_reference_t<T>&, const remove_reference_t<U>&> &&
Predicate<R,
common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>,
common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>> &&
Predicate<R, T, U> && Predicate<R, U, T>;
```

Let

- r be an expression such that decltype((r)) is R,
- t be an expression such that decltype((t)) is T,
- u be an expression such that decltype((u)) is U, and
- C be
common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>

```
template<class R, class T, class U>
concept StrictWeakOrder = Relation<R, T, U>;
```

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

If we define
equiv(a, b)
as
!comp(a, b) && !comp(b, a),
then the requirements are that
comp
and
equiv
both be transitive relations: