[concepts.lang]

# 18 Concepts library [[concepts]](./#concepts)

## 18.4 Language-related concepts [concepts.lang]

### [18.4.1](#general) General [[concepts.lang.general]](concepts.lang.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L293)

Subclause [concepts.lang] contains the definition of concepts corresponding to language
features[.](#general-1.sentence-1)

These concepts express relationships between types, type
classifications, and fundamental type properties[.](#general-1.sentence-2)

### [18.4.2](#concept.same) Concept same_as [[concept.same]](concept.same)

[ð](#concept.same-itemdecl:1)

`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_same_v "21.3.3 Header <type_­traits> synopsis [meta.type.synop]")<T, U>;       // exposition only

template<class T, class U>
  concept [same_as](#concept:same_as "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>;
`

[1](#concept.same-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L309)

[*Note [1](#concept.same-note-1)*:

[same_as](#concept:same_as "18.4.2 Concept same_­as [concept.same]")<T, U> subsumes [same_as](#concept:same_as "18.4.2 Concept same_­as [concept.same]")<U, T> and
vice versa[.](#concept.same-1.sentence-1)

â *end note*]

### [18.4.3](#concept.derived) Concept derived_from [[concept.derived]](concept.derived)

[ð](#concept:derived_from)

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

[1](#concept.derived-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L326)

[*Note [1](#concept.derived-note-1)*:

[derived_from](#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]")<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[.](#concept.derived-1.sentence-1)

â *end note*]

### [18.4.4](#concept.convertible) Concept convertible_to [[concept.convertible]](concept.convertible)

[1](#concept.convertible-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L336)

Given types From and To and
an expression E whose type and value category are the same as those of declval<From>(),[convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<From, To> requires E to be both implicitly and explicitly convertible to type To[.](#concept.convertible-1.sentence-1)

The implicit and explicit conversions are required to produce equal
results[.](#concept.convertible-1.sentence-2)

[ð](#concept:convertible_to)

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

[2](#concept.convertible-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L355)

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 FromR such that f() is equality-preserving[.](#concept.convertible-2.sentence-1)

Types From and To model [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<From, To> only if:

- [(2.1)](#concept.convertible-2.1)

  To is not an object or reference-to-object type, orstatic_cast<To>(f()) is equal to test(f)[.](#concept.convertible-2.1.sentence-1)

- [(2.2)](#concept.convertible-2.2)

  FromR is not a reference-to-object type, or
  * [(2.2.1)](#concept.convertible-2.2.1)

      If FromR 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]](lib.types.movedfrom "16.4.6.17 Moved-from state of library types"))[.](#concept.convertible-2.2.1.sentence-1)

  * [(2.2.2)](#concept.convertible-2.2.2)

      Otherwise, the object referred to by f() is not modified by either above
expression[.](#concept.convertible-2.2.2.sentence-1)

### [18.4.5](#concept.commonref) Concept common_reference_with [[concept.commonref]](concept.commonref)

[1](#concept.commonref-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L390)

For two types T and U, if common_reference_t<T, U> is well-formed and denotes a type C such that both[convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<T, C> and[convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<U, C> are modeled, then T and U share a[*common reference type*](#def:common_reference_type), C[.](#concept.commonref-1.sentence-1)

[*Note [1](#concept.commonref-note-1)*:

C can be the same as T or U, or can be a
different type[.](#concept.commonref-1.sentence-2)

C can be a reference type[.](#concept.commonref-1.sentence-3)

â *end note*]

[ð](#concept:common_reference_with)

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

[2](#concept.commonref-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L412)

Let C be common_reference_t<T, U>[.](#concept.commonref-2.sentence-1)

Let t1 and t2 be equality-preserving
expressions ([[concepts.equality]](concepts.equality "18.2 Equality preservation")) 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[.](#concept.commonref-2.sentence-2)

T and U model [common_reference_with](#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")<T, U> only if

- [(2.1)](#concept.commonref-2.1)

C(t1) equals C(t2) if and only if t1 equals t2, and

- [(2.2)](#concept.commonref-2.2)

C(u1) equals C(u2) if and only if u1 equals u2[.](#concept.commonref-2.sentence-3)

[3](#concept.commonref-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L428)

[*Note [2](#concept.commonref-note-2)*:

Users can customize the behavior of [common_reference_with](#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]") by specializing
the basic_common_reference class template ([[meta.trans.other]](meta.trans.other "21.3.9.7 Other transformations"))[.](#concept.commonref-3.sentence-1)

â *end note*]

### [18.4.6](#concept.common) Concept common_with [[concept.common]](concept.common)

[1](#concept.common-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L437)

If T and U can both be explicitly converted to some third type,C, then T and U share a [*common type*](#def:common_type),C[.](#concept.common-1.sentence-1)

[*Note [1](#concept.common-note-1)*:

C can be the same as T or U, or can be a
different type[.](#concept.common-1.sentence-2)

C is not necessarily unique[.](#concept.common-1.sentence-3)

â *end note*]

[ð](#concept:common_with)

`template<class T, class U>
  concept [common_with](#concept:common_with "18.4.6 Concept common_­with [concept.common]") =
    [same_as](#concept:same_as "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_reference_with "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_reference_with "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>>>;
`

[2](#concept.common-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L465)

Let C be common_type_t<T, U>[.](#concept.common-2.sentence-1)

Let t1 and t2 be
equality-preserving expressions ([[concepts.equality]](concepts.equality "18.2 Equality preservation")) 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[.](#concept.common-2.sentence-2)

T and U model [common_with](#concept:common_with "18.4.6 Concept common_­with [concept.common]")<T, U> only if

- [(2.1)](#concept.common-2.1)

C(t1) equals C(t2) if and only if t1 equals t2, and

- [(2.2)](#concept.common-2.2)

C(u1) equals C(u2) if and only if u1 equals u2[.](#concept.common-2.sentence-3)

[3](#concept.common-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L481)

[*Note [2](#concept.common-note-2)*:

Users can customize the behavior of [common_with](#concept:common_with "18.4.6 Concept common_­with [concept.common]") by specializing thecommon_type class template ([[meta.trans.other]](meta.trans.other "21.3.9.7 Other transformations"))[.](#concept.common-3.sentence-1)

â *end note*]

### [18.4.7](#concepts.arithmetic) Arithmetic concepts [[concepts.arithmetic]](concepts.arithmetic)

[ð](#concepts.arithmetic-itemdecl:1)

`template<class T>
  concept [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [is_integral_v](meta.type.synop#lib:is_integral_v "21.3.3 Header <type_­traits> synopsis [meta.type.synop]")<T>;
template<class T>
  concept [signed_integral](#concept:signed_integral "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_signed_v "21.3.3 Header <type_­traits> synopsis [meta.type.synop]")<T>;
template<class T>
  concept [unsigned_integral](#concept:unsigned_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]")<T> && ![signed_integral](#concept:signed_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]")<T>;
template<class T>
  concept [floating_point](#concept:floating_point "18.4.7 Arithmetic concepts [concepts.arithmetic]") = is_floating_point_v<T>;
`

[1](#concepts.arithmetic-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L502)

[*Note [1](#concepts.arithmetic-note-1)*:

[signed_integral](#concept:signed_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") can be modeled even by types that are
not signed integer types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")); for example, char[.](#concepts.arithmetic-1.sentence-1)

â *end note*]

[2](#concepts.arithmetic-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L508)

[*Note [2](#concepts.arithmetic-note-2)*:

[unsigned_integral](#concept:unsigned_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") can be modeled even by types that are
not unsigned integer types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")); for example, bool[.](#concepts.arithmetic-2.sentence-1)

â *end note*]

### [18.4.8](#concept.assignable) Concept assignable_from [[concept.assignable]](concept.assignable)

[ð](#concept:assignable_from)

`template<class LHS, class RHS>
  concept [assignable_from](#concept:assignable_from "18.4.8 Concept assignable_­from [concept.assignable]") =
    is_lvalue_reference_v<LHS> &&
    [common_reference_with](#concept:common_reference_with "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_as "18.4.2 Concept same_­as [concept.same]")<LHS>;
    };
`

[1](#concept.assignable-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L528)

Let:

- [(1.1)](#concept.assignable-1.1)

lhs be an lvalue that refers to an object lcopy such that decltype((lhs)) is LHS,

- [(1.2)](#concept.assignable-1.2)

rhs be an expression such that decltype((rhs)) is RHS, and

- [(1.3)](#concept.assignable-1.3)

rcopy be a distinct object that is equal to rhs[.](#concept.assignable-1.sentence-1)

LHS and RHS model[assignable_from](#concept:assignable_from "18.4.8 Concept assignable_­from [concept.assignable]")<LHS, RHS> only if

- [(1.4)](#concept.assignable-1.4)

  addressof(lhs = rhs) == addressof(lcopy)[.](#concept.assignable-1.4.sentence-1)

- [(1.5)](#concept.assignable-1.5)

  After evaluating lhs = rhs:
  * [(1.5.1)](#concept.assignable-1.5.1)

      lhs is equal to rcopy, unless rhs is a non-const
xvalue that refers to lcopy[.](#concept.assignable-1.5.1.sentence-1)

  * [(1.5.2)](#concept.assignable-1.5.2)

      If rhs is a non-const xvalue, the resulting state of the
object to which it refers is valid but unspecified ([[lib.types.movedfrom]](lib.types.movedfrom "16.4.6.17 Moved-from state of library types"))[.](#concept.assignable-1.5.2.sentence-1)

  * [(1.5.3)](#concept.assignable-1.5.3)

      Otherwise, if rhs is a glvalue, the object to which it refers is
 not modified[.](#concept.assignable-1.5.3.sentence-1)

[2](#concept.assignable-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L555)

[*Note [1](#concept.assignable-note-1)*:

Assignment need not be a total function ([[structure.requirements]](structure.requirements "16.3.2.3 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 =[.](#concept.assignable-2.sentence-1)

â *end note*]

### [18.4.9](#concept.swappable) Concept swappable [[concept.swappable]](concept.swappable)

[1](#concept.swappable-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L566)

Let t1 and t2 be equality-preserving expressions that denote
distinct equal objects of type T, and let u1 and u2 similarly denote distinct equal objects of type U[.](#concept.swappable-1.sentence-1)

[*Note [1](#concept.swappable-note-1)*:

t1 and u1 can denote distinct objects, or the same object[.](#concept.swappable-1.sentence-2)

â *end note*]

An operation[*exchanges the values*](#def:exchanges_the_values) denoted by t1 and u1 if and only
if the operation modifies neither t2 nor u2 and:

- [(1.1)](#concept.swappable-1.1)

  If T and U are the same type, the result of the operation
 is that t1 equals u2 and u1 equals t2[.](#concept.swappable-1.1.sentence-1)

- [(1.2)](#concept.swappable-1.2)

  If T and U are different types and [common_reference_with](#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")<decltype((t1)), decltype((u1))> is modeled,
 the result of the operation is that C(t1) equals C(u2) and C(u1) equals C(t2) where C is common_reference_t<decltype((t1)), decltype((u1))>[.](#concept.swappable-1.2.sentence-1)

[2](#concept.swappable-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L590)

The name ranges​::​swap denotes a customization point
object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#concept.swappable-2.sentence-1)

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

- [(2.1)](#concept.swappable-2.1)

  S is (void)swap(E1, E2)[192](#footnote-192 "The name swap is used here unqualified.") if E1 or E2 has class or enumeration type ([[basic.compound]](basic.compound "6.9.4 Compound types")) and that expression is valid, with
 overload resolution performed in a context that includes the declarationtemplate<class T>void swap(T&, T&) = delete; and does not include a declaration of ranges​::​swap[.](#concept.swappable-2.1.sentence-1)
  If the function selected by overload resolution does not
 exchange the values denoted by E1 and E2,
 the program is ill-formed, no diagnostic required[.](#concept.swappable-2.1.sentence-2)
  [*Note [2](#concept.swappable-note-2)*:
  This precludes calling unconstrained program-defined overloads of swap[.](#concept.swappable-2.1.sentence-3)
  When the deleted overload is viable, program-defined overloads
 need to be more specialized ([[temp.func.order]](temp.func.order "13.7.7.3 Partial ordering of function templates")) to be selected[.](#concept.swappable-2.1.sentence-4)
 â *end note*]

- [(2.2)](#concept.swappable-2.2)

  Otherwise, if E1 and E2 are lvalues of array types ([[basic.compound]](basic.compound "6.9.4 Compound types"))
 with equal extent and ranges​::​swap(*E1, *E2) is a valid expression, S is (void)ranges​::​swap_ranges(E1, E2),
 except that noexcept(S) is equal to noexcept(​ranges​::​swap(*E1, *E2))[.](#concept.swappable-2.2.sentence-1)

- [(2.3)](#concept.swappable-2.3)

  Otherwise, if E1 and E2 are lvalues of the
 same type T that models [move_constructible](#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]")<T> and [assignable_from](#concept:assignable_from "18.4.8 Concept assignable_­from [concept.assignable]")<T&, T>, S is an expression that exchanges the denoted values[.](#concept.swappable-2.3.sentence-1)
  S is a constant expression if
  * [(2.3.1)](#concept.swappable-2.3.1)

T is a literal type ([[basic.types.general]](basic.types.general#term.literal.type "6.9.1 General")),

  * [(2.3.2)](#concept.swappable-2.3.2)

both E1 = std​::​move(E2) and E2 = std​::​move(E1) are
 constant subexpressions ([[defns.const.subexpr]](defns.const.subexpr "3.15 constant subexpression")), and

  * [(2.3.3)](#concept.swappable-2.3.3)

the full-expressions of the initializers in the declarationsT t1(std::move(E1));
T t2(std::move(E2)); are constant subexpressions.

noexcept(S) is equal to is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>[.](#concept.swappable-2.3.sentence-2)

- [(2.4)](#concept.swappable-2.4)

  Otherwise, ranges​::​swap(E1, E2) is ill-formed[.](#concept.swappable-2.4.sentence-1)
  [*Note [3](#concept.swappable-note-3)*:
  This case can result in substitution failure when ranges​::​swap(E1, E2) appears in the immediate context of a template instantiation[.](#concept.swappable-2.4.sentence-2)
 â *end note*]

[3](#concept.swappable-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L660)

[*Note [4](#concept.swappable-note-4)*:

Whenever ranges​::​swap(E1, E2) is a valid expression, it
exchanges the values denoted byE1 and E2 and has type void[.](#concept.swappable-3.sentence-1)

â *end note*]

[ð](#concept:swappable)

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

[ð](#concept:swappable_with)

`template<class T, class U>
  concept [swappable_with](#concept:swappable_with "18.4.9 Concept swappable [concept.swappable]") =
    [common_reference_with](#concept:common_reference_with "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));
    };
`

[4](#concept.swappable-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L684)

[*Note [5](#concept.swappable-note-5)*:

The semantics of the [swappable](#concept:swappable "18.4.9 Concept swappable [concept.swappable]") and [swappable_with](#concept:swappable_with "18.4.9 Concept swappable [concept.swappable]") concepts are fully defined by the ranges​::​swap customization point object[.](#concept.swappable-4.sentence-1)

â *end note*]

[5](#concept.swappable-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L690)

[*Example [1](#concept.swappable-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](#concept:swappable_with "18.4.9 Concept swappable [concept.swappable]")<T> U>void value_swap(T&& t, U&& u) { ranges::swap(std::forward<T>(t), std::forward<U>(u));}template<std::[swappable](#concept:swappable "18.4.9 Concept swappable [concept.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*]

[192)](#footnote-192)[192)](#footnoteref-192)

The name swap is used
 here unqualified[.](#footnote-192.sentence-1)

### [18.4.10](#concept.destructible) Concept destructible [[concept.destructible]](concept.destructible)

[1](#concept.destructible-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L737)

The [destructible](#concept:destructible "18.4.10 Concept destructible [concept.destructible]") concept specifies properties of all types,
instances of which can be destroyed at the end of their lifetime, or reference
types[.](#concept.destructible-1.sentence-1)

[ð](#concept:destructible)

`template<class T>
  concept [destructible](#concept:destructible "18.4.10 Concept destructible [concept.destructible]") = [is_nothrow_destructible_v](meta.type.synop#lib:is_nothrow_destructible_v "21.3.3 Header <type_­traits> synopsis [meta.type.synop]")<T>;
`

[2](#concept.destructible-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L748)

[*Note [1](#concept.destructible-note-1)*:

Unlike the [*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") requirements (Table [35](utility.arg.requirements#tab:cpp17.destructible "Table 35: Cpp17Destructible requirements")), this
concept forbids destructors that are potentially throwing, even if a particular
invocation of the destructor does not actually throw[.](#concept.destructible-2.sentence-1)

â *end note*]

### [18.4.11](#concept.constructible) Concept constructible_from [[concept.constructible]](concept.constructible)

[1](#concept.constructible-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L758)

The [constructible_from](#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") concept constrains the initialization of a
variable of a given type with a particular set of argument types[.](#concept.constructible-1.sentence-1)

[ð](#concept:constructible_from)

`template<class T, class... Args>
  concept [constructible_from](#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") = [destructible](#concept:destructible "18.4.10 Concept destructible [concept.destructible]")<T> && [is_constructible_v](meta.type.synop#lib:is_constructible_v "21.3.3 Header <type_­traits> synopsis [meta.type.synop]")<T, Args...>;
`

### [18.4.12](#concept.default.init) Concept default_initializable [[concept.default.init]](concept.default.init)

[ð](#concept:default_initializable)

`template<class T>
  constexpr bool is-default-initializable = see below;         // exposition only

template<class T>
  concept [default_initializable](#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = [constructible_from](#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<T> &&
                                  requires { T{}; } &&
                                  is-default-initializable<T>;
`

[1](#concept.default.init-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L780)

For a type T, *is-default-initializable*<T> is true if and only if the variable definitionT t; is well-formed for some invented variable t;
otherwise it is false[.](#concept.default.init-1.sentence-1)

Access checking is performed as if in a context unrelated to T[.](#concept.default.init-1.sentence-2)

Only the validity of the immediate context of the variable initialization is considered[.](#concept.default.init-1.sentence-3)

### [18.4.13](#concept.moveconstructible) Concept move_constructible [[concept.moveconstructible]](concept.moveconstructible)

[ð](#concept:move_constructible)

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

[1](#concept.moveconstructible-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L800)

If T is an object type, then let rv be an rvalue of typeT and u2 a distinct object of type T equal torv[.](#concept.moveconstructible-1.sentence-1)

T models [move_constructible](#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") only if

- [(1.1)](#concept.moveconstructible-1.1)

  After the definition T u = rv;, u is equal to u2[.](#concept.moveconstructible-1.1.sentence-1)

- [(1.2)](#concept.moveconstructible-1.2)

  T(rv) is equal to u2[.](#concept.moveconstructible-1.2.sentence-1)

- [(1.3)](#concept.moveconstructible-1.3)

  If T is not const, rv's resulting state is valid
but unspecified ([[lib.types.movedfrom]](lib.types.movedfrom "16.4.6.17 Moved-from state of library types")); otherwise, it is unchanged[.](#concept.moveconstructible-1.3.sentence-1)

### [18.4.14](#concept.copyconstructible) Concept copy_constructible [[concept.copyconstructible]](concept.copyconstructible)

[ð](#concept:copy_constructible)

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

[1](#concept.copyconstructible-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L826)

If T is an object type, then let v be an lvalue of typeT or const T or an rvalue of type const T[.](#concept.copyconstructible-1.sentence-1)

T models [copy_constructible](#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") only if

- [(1.1)](#concept.copyconstructible-1.1)

  After the definition T u = v;,u is equal to v ([[concepts.equality]](concepts.equality "18.2 Equality preservation")) andv is not modified[.](#concept.copyconstructible-1.1.sentence-1)

- [(1.2)](#concept.copyconstructible-1.2)

  T(v) is equal to v and does not modify v[.](#concept.copyconstructible-1.2.sentence-1)
