[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 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 synopsis [meta.type.synop]"); // exposition only template 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]") && [same-as-impl](#concept:same-as-impl "18.4.2 Concept same_­as [concept.same]"); ` [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]") subsumes [same_as](#concept:same_as "18.4.2 Concept same_­as [concept.same]") 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 concept [derived_from](#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]") = is_base_of_v && is_convertible_v; ` [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]") 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(),[convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") 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 concept [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") = is_convertible_v && requires { static_cast(declval()); }; ` [2](#concept.convertible-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L355) Let FromR be add_rvalue_reference_t 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]") only if: - [(2.1)](#concept.convertible-2.1) To is not an object or reference-to-object type, orstatic_cast(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 is well-formed and denotes a type C such that both[convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") and[convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") 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 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> && [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")> && [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")>; ` [2](#concept.commonref-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L412) Let C be common_reference_t[.](#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]") 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 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> && requires { static_cast>(declval()); static_cast>(declval()); } && [common_reference_with](#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")< add_lvalue_reference_t, add_lvalue_reference_t> && [common_reference_with](#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")< add_lvalue_reference_t>, common_reference_t< add_lvalue_reference_t, add_lvalue_reference_t>>; ` [2](#concept.common-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L465) Let C be common_type_t[.](#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]") 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 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 synopsis [meta.type.synop]"); template concept [signed_integral](#concept:signed_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") && [is_signed_v](meta.type.synop#lib:is_signed_v "21.3.3 Header synopsis [meta.type.synop]"); template concept [unsigned_integral](#concept:unsigned_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") && ![signed_integral](#concept:signed_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]"); template concept [floating_point](#concept:floating_point "18.4.7 Arithmetic concepts [concepts.arithmetic]") = is_floating_point_v; ` [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 concept [assignable_from](#concept:assignable_from "18.4.8 Concept assignable_­from [concept.assignable]") = is_lvalue_reference_v && [common_reference_with](#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")&, const remove_reference_t&> && requires(LHS lhs, RHS&& rhs) { { lhs = std::forward(rhs) } -> [same_as](#concept:same_as "18.4.2 Concept same_­as [concept.same]"); }; ` [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]") 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]") 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[.](#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 declarationtemplatevoid 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]") and [assignable_from](#concept:assignable_from "18.4.8 Concept assignable_­from [concept.assignable]"), 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 && is_nothrow_move_assignable_v[.](#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 concept [swappable](#concept:swappable "18.4.9 Concept swappable [concept.swappable]") = requires(T& a, T& b) { ranges::swap(a, b); }; ` [🔗](#concept:swappable_with) `template 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]") && requires(T&& t, U&& u) { ranges::swap(std::forward(t), std::forward(t)); ranges::swap(std::forward(u), std::forward(u)); ranges::swap(std::forward(t), std::forward(u)); ranges::swap(std::forward(u), std::forward(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 #include #include namespace ranges = std::ranges; template U>void value_swap(T&& t, U&& u) { ranges::swap(std::forward(t), std::forward(u));}templatevoid 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 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 synopsis [meta.type.synop]"); ` [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 concept [constructible_from](#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") = [destructible](#concept:destructible "18.4.10 Concept destructible [concept.destructible]") && [is_constructible_v](meta.type.synop#lib:is_constructible_v "21.3.3 Header synopsis [meta.type.synop]"); ` ### [18.4.12](#concept.default.init) Concept default_initializable [[concept.default.init]](concept.default.init) [🔗](#concept:default_initializable) `template constexpr bool is-default-initializable = see below; // exposition only template 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]") && requires { T{}; } && is-default-initializable; ` [1](#concept.default.init-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L780) For a type T, *is-default-initializable* 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 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]") && [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"); ` [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 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]") && [constructible_from](#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") && [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") && [constructible_from](#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") && [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") && [constructible_from](#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") && [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"); ` [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)