[meta.unary] # 21 Metaprogramming library [[meta]](./#meta) ## 21.3 Metaprogramming and type traits [[type.traits]](type.traits#meta.unary) ### 21.3.6 Unary type traits [meta.unary] #### [21.3.6.1](#general) General [[meta.unary.general]](meta.unary.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L913) Subclause [meta.unary] contains templates that may be used to query the properties of a type at compile time[.](#general-1.sentence-1) [2](#general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L917) Each of these templates shall be a[*Cpp17UnaryTypeTrait*](meta.rqmts#:Cpp17UnaryTypeTrait "21.3.2 Requirements [meta.rqmts]") with a base characteristic oftrue_type if the corresponding condition is true, otherwisefalse_type[.](#general-2.sentence-1) #### [21.3.6.2](#cat) Primary type categories [[meta.unary.cat]](meta.unary.cat) [1](#cat-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L926) The primary type categories specified in Table [52](#tab:meta.unary.cat "Table 52: Primary type category predicates") correspond to the descriptions given in subclause [[basic.types]](basic.types "6.9 Types") of the C++ standard[.](#cat-1.sentence-1) [2](#cat-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L931) For any given type T, the result of applying one of these templates toT and to cv T shall yield the same result[.](#cat-2.sentence-1) [3](#cat-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L935) [*Note [1](#cat-note-1)*: For any given type T, exactly one of the primary type categories has a value member that evaluates to true[.](#cat-3.sentence-1) — *end note*] Table [52](#tab:meta.unary.cat) — Primary type category predicates [[tab:meta.unary.cat]](./tab:meta.unary.cat) | [🔗](#tab:meta.unary.cat-row-1)
**Template** | **Condition** | **Comments** | | --- | --- | --- | | [🔗](#tab:meta.unary.cat-row-2)
template struct [is_void](#lib:is_void "21.3.6.2 Primary type categories [meta.unary.cat]"); | T is void | | | [🔗](#tab:meta.unary.cat-row-3)
template struct [is_null_pointer](#lib:is_null_pointer "21.3.6.2 Primary type categories [meta.unary.cat]"); | T is nullptr_t ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")) | | | [🔗](#tab:meta.unary.cat-row-4)
template struct [is_integral](#lib:is_integral "21.3.6.2 Primary type categories [meta.unary.cat]"); | T is an integral type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")) | | | [🔗](#tab:meta.unary.cat-row-5)
template struct is_floating_point; | T is a floating-point type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")) | | | [🔗](#tab:meta.unary.cat-row-6)
template struct is_array; | T is an array type ([[basic.compound]](basic.compound "6.9.4 Compound types")) of known or unknown extent | Class template array ([[array]](array "23.3.3 Class template array")) is not an array type[.](#tab:meta.unary.cat-row-6-column-3-sentence-1) | | [🔗](#tab:meta.unary.cat-row-7)
template struct is_pointer; | T is a pointer type ([[basic.compound]](basic.compound "6.9.4 Compound types")) | Includes pointers to functions but not pointers to non-static members[.](#tab:meta.unary.cat-row-7-column-3-sentence-1) | | [🔗](#tab:meta.unary.cat-row-8)
template struct is_lvalue_reference; | T is an lvalue reference type ([[dcl.ref]](dcl.ref "9.3.4.3 References")) | | | [🔗](#tab:meta.unary.cat-row-9)
template struct is_rvalue_reference; | T is an rvalue reference type ([[dcl.ref]](dcl.ref "9.3.4.3 References")) | | | [🔗](#tab:meta.unary.cat-row-10)
template struct is_member_object_pointer; | T is a pointer to data member | | | [🔗](#tab:meta.unary.cat-row-11)
template struct is_member_function_pointer; | T is a pointer to member function | | | [🔗](#tab:meta.unary.cat-row-12)
template struct is_enum; | T is an enumeration type ([[basic.compound]](basic.compound "6.9.4 Compound types")) | | | [🔗](#tab:meta.unary.cat-row-13)
template struct is_union; | T is a union type ([[basic.compound]](basic.compound "6.9.4 Compound types")) | | | [🔗](#tab:meta.unary.cat-row-14)
template struct is_class; | T is a non-union class type ([[basic.compound]](basic.compound "6.9.4 Compound types")) | | | [🔗](#tab:meta.unary.cat-row-15)
template struct is_function; | T is a function type ([[basic.compound]](basic.compound "6.9.4 Compound types")) | | | [🔗](#tab:meta.unary.cat-row-16)
template struct is_reflection; | T is std​::​meta​::​info ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")) | | #### [21.3.6.3](#comp) Composite type traits [[meta.unary.comp]](meta.unary.comp) [1](#comp-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1014) The templates specified in Table [53](#tab:meta.unary.comp "Table 53: Composite type category predicates") provide convenient compositions of the primary type categories, corresponding to the descriptions given in subclause [[basic.types]](basic.types "6.9 Types")[.](#comp-1.sentence-1) [2](#comp-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1019) For any given type T, the result of applying one of these templates toT and to cv T shall yield the same result[.](#comp-2.sentence-1) Table [53](#tab:meta.unary.comp) — Composite type category predicates [[tab:meta.unary.comp]](./tab:meta.unary.comp) | [🔗](#tab:meta.unary.comp-row-1)
**Template** | **Condition** | **Comments** | | --- | --- | --- | | [🔗](#tab:meta.unary.comp-row-2)
template struct is_reference; | T is an lvalue reference or an rvalue reference | | | [🔗](#tab:meta.unary.comp-row-3)
template struct is_arithmetic; | T is an arithmetic type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")) | | | [🔗](#tab:meta.unary.comp-row-4)
template struct is_fundamental; | T is a fundamental type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")) | | | [🔗](#tab:meta.unary.comp-row-5)
template struct is_object; | T is an object type ([[basic.types.general]](basic.types.general#term.object.type "6.9.1 General")) | | | [🔗](#tab:meta.unary.comp-row-6)
template struct is_scalar; | T is a scalar type ([[basic.types.general]](basic.types.general#term.scalar.type "6.9.1 General")) | | | [🔗](#tab:meta.unary.comp-row-7)
template struct is_compound; | T is a compound type ([[basic.compound]](basic.compound "6.9.4 Compound types")) | | | [🔗](#tab:meta.unary.comp-row-8)
template struct is_member_pointer; | T is a pointer-to-member type ([[basic.compound]](basic.compound "6.9.4 Compound types")) | | #### [21.3.6.4](#prop) Type properties [[meta.unary.prop]](meta.unary.prop) [1](#prop-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1063) The templates specified in Table [54](#tab:meta.unary.prop "Table 54: Type property predicates") provide access to some of the more important properties of types[.](#prop-1.sentence-1) [2](#prop-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1067) It is unspecified whether the library defines any full or partial specializations of any of these templates[.](#prop-2.sentence-1) [3](#prop-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1071) For all of the class templates X declared in this subclause, instantiating that template with a template-argument that is a class template specialization may result in the implicit instantiation of the template argument if and only if the semantics of X require that the argument is a complete type[.](#prop-3.sentence-1) [4](#prop-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1078) For the purpose of defining the templates in this subclause, a function call expression declval() for any type T is considered to be a trivial ([[depr.meta.types]](depr.meta.types#term.trivial.type "D.13 Deprecated type traits"), [[special]](special "11.4.4 Special member functions")) function call that is not an odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule")) of declval in the context of the corresponding definition notwithstanding the restrictions of [[declval]](declval "22.2.6 Function template declval")[.](#prop-4.sentence-1) [5](#prop-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1086) For the purpose of defining the templates in this subclause, let *VAL* for some type T be an expression defined as follows: - [(5.1)](#prop-5.1) If T is a reference or function type,*VAL* is an expression with the same type and value category as declval()[.](#prop-5.1.sentence-1) - [(5.2)](#prop-5.2) Otherwise, *VAL* is a prvalue that initially has type T[.](#prop-5.2.sentence-1) [*Note [1](#prop-note-1)*: If T is cv-qualified, the cv-qualification is subject to adjustment ([[expr.type]](expr.type "7.2.2 Type"))[.](#prop-5.2.sentence-2) — *end note*] Table [54](#tab:meta.unary.prop) — Type property predicates [[tab:meta.unary.prop]](./tab:meta.unary.prop) | [🔗](#tab:meta.unary.prop-row-1)
**Template** | **Condition** | **Preconditions** | | --- | --- | --- | | [🔗](#tab:meta.unary.prop-row-2)
template struct is_const; | T is const-qualified ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers")) | | | [🔗](#tab:meta.unary.prop-row-3)
template struct is_volatile; | T is volatile-qualified ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers")) | | | [🔗](#tab:meta.unary.prop-row-4)
template struct is_trivially_copyable; | T is a trivially copyable type ([[basic.types.general]](basic.types.general#term.trivially.copyable.type "6.9.1 General")) | remove_all_extents_t shall be a complete type or cv void[.](#tab:meta.unary.prop-row-4-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-5)
template struct is_trivially_relocatable; | T is a trivially relocatable type ([[basic.types.general]](basic.types.general "6.9.1 General")) | remove_all_extents_t shall be a complete type or cv void[.](#tab:meta.unary.prop-row-5-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-6)
template struct is_replaceable; | T is a replaceable type ([[basic.types.general]](basic.types.general "6.9.1 General")) | remove_all_extents_t shall be a complete type or cv void[.](#tab:meta.unary.prop-row-6-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-7)
template struct is_standard_layout; | T is a standard-layout type ([[basic.types.general]](basic.types.general#term.standard.layout.type "6.9.1 General")) | remove_all_extents_t shall be a complete type or cv void[.](#tab:meta.unary.prop-row-7-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-8)
template struct is_empty; | T is a class type, but not a union type, with no non-static data members other than subobjects of zero size, no virtual member functions, no virtual base classes, and no base class B for which is_empty_v is false[.](#tab:meta.unary.prop-row-8-column-2-sentence-1) | If T is a non-union class type, T shall be a complete type[.](#tab:meta.unary.prop-row-8-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-9)
template struct is_polymorphic; | T is a polymorphic class ([[class.virtual]](class.virtual "11.7.3 Virtual functions")) | If T is a non-union class type, T shall be a complete type[.](#tab:meta.unary.prop-row-9-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-10)
template struct is_abstract; | T is an abstract class ([[class.abstract]](class.abstract "11.7.4 Abstract classes")) | If T is a non-union class type, T shall be a complete type[.](#tab:meta.unary.prop-row-10-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-11)
template struct is_final; | T is a class type marked with the [*class-property-specifier*](class.pre#nt:class-property-specifier "11.1 Preamble [class.pre]")final ([[class.pre]](class.pre "11.1 Preamble"))[.](#tab:meta.unary.prop-row-11-column-2-sentence-1)
[*Note [2](#tab:meta.unary.prop-row-11-column-2-note-2)*:
A union is a class type that can be marked with final[.](#tab:meta.unary.prop-row-11-column-2-sentence-2) — *end note*] | If T is a class type, T shall be a complete type[.](#tab:meta.unary.prop-row-11-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-12)
template struct [is_aggregate](#lib:is_aggregate "21.3.6.4 Type properties [meta.unary.prop]"); | T is an aggregate type ([[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates")) | T shall be an array type, a complete type, or cv void[.](#tab:meta.unary.prop-row-12-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-13)
template struct is_consteval_only; | T is consteval-only ([[basic.types.general]](basic.types.general "6.9.1 General")) | remove_all_extents_t shall be a complete type or cv void[.](#tab:meta.unary.prop-row-13-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-14)
template struct is_signed; | If is_arithmetic_v is true, the same result as T(-1) < T(0); otherwise, false | | | [🔗](#tab:meta.unary.prop-row-15)
template struct [is_unsigned](#lib:is_unsigned "21.3.6.4 Type properties [meta.unary.prop]"); | If is_arithmetic_v is true, the same result as T(0) < T(-1); otherwise, false | | | [🔗](#tab:meta.unary.prop-row-16)
template struct [is_bounded_array](#lib:is_bounded_array "21.3.6.4 Type properties [meta.unary.prop]"); | T is an array type of known bound ([[dcl.array]](dcl.array "9.3.4.5 Arrays")) | | | [🔗](#tab:meta.unary.prop-row-17)
template struct is_unbounded_array; | T is an array type of unknown bound ([[dcl.array]](dcl.array "9.3.4.5 Arrays")) | | | [🔗](#tab:meta.unary.prop-row-18)
template struct is_scoped_enum; | T is a scoped enumeration ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")) | | | [🔗](#tab:meta.unary.prop-row-19)
template struct is_constructible; | For a function type T or for a cv void type T, is_constructible_v is false, otherwise *see below* | T and all types in the template parameter pack Args shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.unary.prop-row-19-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-20)
template struct is_default_constructible; | is_constructible_v is true[.](#tab:meta.unary.prop-row-20-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-20-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-21)
template struct is_copy_constructible; | For a referenceable type T ([[defns.referenceable]](defns.referenceable "3.45 referenceable type")), the same result as is_constructible_v, otherwise false[.](#tab:meta.unary.prop-row-21-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-21-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-22)
template struct is_move_constructible; | For a referenceable type T, the same result as is_constructible_v, otherwise false[.](#tab:meta.unary.prop-row-22-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-22-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-23)
template struct is_assignable; | The expression declval() = declval() is well-formed when treated as an unevaluated operand ([[expr.context]](expr.context#term.unevaluated.operand "7.2.3 Context dependence"))[.](#tab:meta.unary.prop-row-23-column-2-sentence-1)
Access checking is performed as if in a context unrelated to T and U[.](#tab:meta.unary.prop-row-23-column-2-sentence-2)
Only the validity of the immediate context of the assignment expression is considered[.](#tab:meta.unary.prop-row-23-column-2-sentence-3)
[*Note [3](#tab:meta.unary.prop-row-23-column-2-note-3)*:
The compilation of the expression can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on[.](#tab:meta.unary.prop-row-23-column-2-sentence-4)
Such side effects are not in the “immediate context” and can result in the program being ill-formed[.](#tab:meta.unary.prop-row-23-column-2-sentence-5) — *end note*] | T and U shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.unary.prop-row-23-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-24)
template struct is_copy_assignable; | For a referenceable type T, the same result as is_assignable_v, otherwise false[.](#tab:meta.unary.prop-row-24-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-24-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-25)
template struct is_move_assignable; | For a referenceable type T, the same result as is_assignable_v, otherwise false[.](#tab:meta.unary.prop-row-25-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-25-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-26)
template struct is_swappable_with; | The expressions swap(declval(), declval()) and swap(declval(), declval()) are each well-formed when treated as an unevaluated operand ([[expr.context]](expr.context#term.unevaluated.operand "7.2.3 Context dependence")) in an overload-resolution context for swappable values ([[swappable.requirements]](swappable.requirements "16.4.4.3 Swappable requirements"))[.](#tab:meta.unary.prop-row-26-column-2-sentence-1)
Access checking is performed as if in a context unrelated to T and U[.](#tab:meta.unary.prop-row-26-column-2-sentence-2)
Only the validity of the immediate context of the swap expressions is considered[.](#tab:meta.unary.prop-row-26-column-2-sentence-3)
[*Note [4](#tab:meta.unary.prop-row-26-column-2-note-4)*:
The compilation of the expressions can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on[.](#tab:meta.unary.prop-row-26-column-2-sentence-4)
Such side effects are not in the “immediate context” and can result in the program being ill-formed[.](#tab:meta.unary.prop-row-26-column-2-sentence-5) — *end note*] | T and U shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.unary.prop-row-26-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-27)
template struct is_swappable; | For a referenceable type T, the same result as is_swappable_with_v, otherwise false[.](#tab:meta.unary.prop-row-27-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-27-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-28)
template struct is_destructible; | Either T is a reference type, or T is a complete object type for which the expression declval().~U() is well-formed when treated as an unevaluated operand ([[expr.context]](expr.context#term.unevaluated.operand "7.2.3 Context dependence")), where U is remove_all_extents_t[.](#tab:meta.unary.prop-row-28-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-28-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-29)
template struct is_trivially_constructible; | is_constructible_v is true and the variable definition for is_constructible, as defined below, is known to call no operation that is not trivial ([[depr.meta.types]](depr.meta.types#term.trivial.type "D.13 Deprecated type traits"), [[special]](special "11.4.4 Special member functions"))[.](#tab:meta.unary.prop-row-29-column-2-sentence-1) | T and all types in the template parameter pack Args shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.unary.prop-row-29-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-30)
template struct is_trivially_default_constructible; | is_trivially_constructible_v is true[.](#tab:meta.unary.prop-row-30-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-30-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-31)
template struct is_trivially_copy_constructible; | For a referenceable type T, the same result as is_trivially_constructible_v, otherwise false[.](#tab:meta.unary.prop-row-31-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-31-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-32)
template struct is_trivially_move_constructible; | For a referenceable type T, the same result as is_trivially_constructible_v, otherwise false[.](#tab:meta.unary.prop-row-32-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-32-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-33)
template struct is_trivially_assignable; | is_assignable_v is true and the assignment, as defined by is_assignable, is known to call no operation that is not trivial ([[depr.meta.types]](depr.meta.types#term.trivial.type "D.13 Deprecated type traits"), [[special]](special "11.4.4 Special member functions"))[.](#tab:meta.unary.prop-row-33-column-2-sentence-1) | T and U shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.unary.prop-row-33-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-34)
template struct is_trivially_copy_assignable; | For a referenceable type T, the same result as is_trivially_assignable_v, otherwise false[.](#tab:meta.unary.prop-row-34-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-34-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-35)
template struct is_trivially_move_assignable; | For a referenceable type T, the same result as is_trivially_assignable_v, otherwise false[.](#tab:meta.unary.prop-row-35-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-35-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-36)
template struct is_trivially_destructible; | is_destructible_v is true and remove_all_extents_t is either a non-class type or a class type with a trivial destructor[.](#tab:meta.unary.prop-row-36-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-36-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-37)
template struct is_nothrow_constructible; | is_constructible_v is true and the variable definition for is_constructible, as defined below, is known not to throw any exceptions ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7 noexcept operator"))[.](#tab:meta.unary.prop-row-37-column-2-sentence-1) | T and all types in the template parameter pack Args shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.unary.prop-row-37-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-38)
template struct is_nothrow_default_constructible; | is_nothrow_constructible_v is true[.](#tab:meta.unary.prop-row-38-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-38-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-39)
template struct is_nothrow_copy_constructible; | For a referenceable type T, the same result as is_nothrow_constructible_v, otherwise false[.](#tab:meta.unary.prop-row-39-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-39-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-40)
template struct is_nothrow_move_constructible; | For a referenceable type T, the same result as is_nothrow_constructible_v, otherwise false[.](#tab:meta.unary.prop-row-40-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-40-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-41)
template struct is_nothrow_assignable; | is_assignable_v is true and the assignment is known not to throw any exceptions ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7 noexcept operator"))[.](#tab:meta.unary.prop-row-41-column-2-sentence-1) | T and U shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.unary.prop-row-41-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-42)
template struct is_nothrow_copy_assignable; | For a referenceable type T, the same result as is_nothrow_assignable_v, otherwise false[.](#tab:meta.unary.prop-row-42-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-42-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-43)
template struct is_nothrow_move_assignable; | For a referenceable type T, the same result as is_nothrow_assignable_v, otherwise false[.](#tab:meta.unary.prop-row-43-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-43-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-44)
template struct is_nothrow_swappable_with; | is_swappable_with_v is true and each swap expression of the definition of is_swappable_with is known not to throw any exceptions ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7 noexcept operator"))[.](#tab:meta.unary.prop-row-44-column-2-sentence-1) | T and U shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.unary.prop-row-44-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-45)
template struct is_nothrow_swappable; | For a referenceable type T, the same result as is_nothrow_swappable_with_v, otherwise false[.](#tab:meta.unary.prop-row-45-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-45-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-46)
template struct is_nothrow_destructible; | is_destructible_v is true and the indicated destructor is known not to throw any exceptions ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7 noexcept operator"))[.](#tab:meta.unary.prop-row-46-column-2-sentence-1) | T shall be a complete type, cv void, or an array of unknown bound[.](#tab:meta.unary.prop-row-46-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-47)
template struct is_nothrow_relocatable; | is_trivially_relocatable_v ||(is_nothrow_move_constructible_v> && is_nothrow_destructible_v>) | remove_all_extents_t shall be a complete type or cv void[.](#tab:meta.unary.prop-row-47-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-48)
template struct is_implicit_lifetime; | T is an implicit-lifetime type ([[basic.types.general]](basic.types.general#term.implicit.lifetime.type "6.9.1 General"))[.](#tab:meta.unary.prop-row-48-column-2-sentence-1) | T shall be an array type, a complete type, or cv void[.](#tab:meta.unary.prop-row-48-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-49)
template struct has_virtual_destructor; | T has a virtual destructor ([[class.dtor]](class.dtor "11.4.7 Destructors")) | If T is a non-union class type, T shall be a complete type[.](#tab:meta.unary.prop-row-49-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-50)
template struct has_unique_object_representations; | For an array type T, the same result as has_unique_object_representations_v>, otherwise *see below*[.](#tab:meta.unary.prop-row-50-column-2-sentence-1) | remove_all_extents_t shall be a complete type or cv void[.](#tab:meta.unary.prop-row-50-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-51)
template struct reference_constructs_from_temporary; | T is a reference type, and the initialization T t(*VAL*); is well-formed and binds t to a temporary object whose lifetime is extended ([[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#tab:meta.unary.prop-row-51-column-2-sentence-1)
Access checking is performed as if in a context unrelated to T and U[.](#tab:meta.unary.prop-row-51-column-2-sentence-2)
Only the validity of the immediate context of the variable initialization is considered[.](#tab:meta.unary.prop-row-51-column-2-sentence-3)
[*Note [5](#tab:meta.unary.prop-row-51-column-2-note-5)*:
The initialization can result in effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on[.](#tab:meta.unary.prop-row-51-column-2-sentence-4)
Such effects are not in the “immediate context” and can result in the program being ill-formed[.](#tab:meta.unary.prop-row-51-column-2-sentence-5) — *end note*] | T and U shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.unary.prop-row-51-column-3-sentence-1) | | [🔗](#tab:meta.unary.prop-row-52)
template struct reference_converts_from_temporary; | T is a reference type, and the initialization T t = *VAL*; is well-formed and binds t to a temporary object whose lifetime is extended ([[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#tab:meta.unary.prop-row-52-column-2-sentence-1)
Access checking is performed as if in a context unrelated to T and U[.](#tab:meta.unary.prop-row-52-column-2-sentence-2)
Only the validity of the immediate context of the variable initialization is considered[.](#tab:meta.unary.prop-row-52-column-2-sentence-3)
[*Note [6](#tab:meta.unary.prop-row-52-column-2-note-6)*:
The initialization can result in effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on[.](#tab:meta.unary.prop-row-52-column-2-sentence-4)
Such effects are not in the “immediate context” and can result in the program being ill-formed[.](#tab:meta.unary.prop-row-52-column-2-sentence-5) — *end note*] | T and U shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.unary.prop-row-52-column-3-sentence-1) | [6](#prop-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1590) [*Example [1](#prop-example-1)*: is_const_v // true is_const_v // false is_const_v // false is_const_v // false is_const_v // true — *end example*] [7](#prop-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1601) [*Example [2](#prop-example-2)*: remove_const_t // volatile int remove_const_t // const int* remove_const_t // const int& remove_const_t // int[3] — *end example*] [8](#prop-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1611) [*Example [3](#prop-example-3)*: // Given:struct P final { };union U1 { };union U2 final { }; // the following assertions hold:static_assert(!is_final_v);static_assert(is_final_v

);static_assert(!is_final_v);static_assert(is_final_v); — *end example*] [9](#prop-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1628) The predicate condition for a template specializationis_constructible shall be satisfied if and only if the following variable definition would be well-formed for some invented variable t: T t(declval()...); [*Note [7](#prop-note-7)*: These tokens are never interpreted as a function declaration[.](#prop-9.sentence-2) — *end note*] Access checking is performed as if in a context unrelated to T and any of the Args[.](#prop-9.sentence-3) Only the validity of the immediate context of the variable initialization is considered[.](#prop-9.sentence-4) [*Note [8](#prop-note-8)*: The evaluation of the initialization can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on[.](#prop-9.sentence-5) Such side effects are not in the “immediate context” and can result in the program being ill-formed[.](#prop-9.sentence-6) — *end note*] [10](#prop-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1652) The predicate condition for a template specializationhas_unique_object_representations shall be satisfied if and only if - [(10.1)](#prop-10.1) T is trivially copyable, and - [(10.2)](#prop-10.2) any two objects of type T with the same value have the same object representation, where * [(10.2.1)](#prop-10.2.1) two objects of array or non-union class type are considered to have the same value if their respective sequences of direct subobjects have the same values, and * [(10.2.2)](#prop-10.2.2) two objects of union type are considered to have the same value if they have the same active member and the corresponding members have the same value[.](#prop-10.sentence-1) The set of scalar types for which this condition holds isimplementation-defined[.](#prop-10.sentence-2) [*Note [9](#prop-note-9)*: If a type has padding bits, the condition does not hold; otherwise, the condition holds true for integral types[.](#prop-10.sentence-3) — *end note*]