[meta.unary.prop]

# 21 Metaprogramming library [[meta]](./#meta)

## 21.3 Metaprogramming and type traits [[type.traits]](type.traits#meta.unary.prop)

### 21.3.6 Unary type traits [[meta.unary]](meta.unary#prop)

#### 21.3.6.4 Type properties [meta.unary.prop]

[1](#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[.](#1.sentence-1)

[2](#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[.](#2.sentence-1)

[3](#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[.](#3.sentence-1)

[4](#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<T>() 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")[.](#4.sentence-1)

[5](#5)

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

For the purpose of defining the templates in this subclause,
let *VAL*<T> for some type T be
an expression defined as follows:

- [(5.1)](#5.1)

  If T is a reference or function type,*VAL*<T> is an expression
with the same type and value category as declval<T>()[.](#5.1.sentence-1)

- [(5.2)](#5.2)

  Otherwise, *VAL*<T> is a prvalue
that initially has type T[.](#5.2.sentence-1)
  [*Note [1](#note-1)*:
  If T is cv-qualified,
the cv-qualification is subject to adjustment ([[expr.type]](expr.type "7.2.2 Type"))[.](#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)<br>**Template** | **Condition** | **Preconditions** |
| --- | --- | --- |
| [ð](#tab:meta.unary.prop-row-2)<br>template<class T>   struct is_const; | T is const-qualified ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers")) |  |
| [ð](#tab:meta.unary.prop-row-3)<br>template<class T>   struct is_volatile; | T is volatile-qualified ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers")) |  |
| [ð](#tab:meta.unary.prop-row-4)<br>template<class T>   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<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)<br>template<class T>   struct is_trivially_relocatable; | T is a trivially relocatable type ([[basic.types.general]](basic.types.general "6.9.1 General")) | remove_all_extents_t<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)<br>template<class T>   struct is_replaceable; | T is a replaceable type ([[basic.types.general]](basic.types.general "6.9.1 General")) | remove_all_extents_t<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)<br>template<class T>   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<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)<br>template<class T>   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<B> 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)<br>template<class T>   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)<br>template<class T>   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)<br>template<class T>   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)<br>[*Note [2](#tab:meta.unary.prop-row-11-column-2-note-2)*:<br>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)<br>template<class T>   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)<br>template<class T>   struct is_consteval_only; | T is consteval-only ([[basic.types.general]](basic.types.general "6.9.1 General")) | remove_all_extents_t<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)<br>template<class T>   struct is_signed; | If is_arithmetic_v<T> is true, the same result as  T(-1) < T(0);  otherwise, false |  |
| [ð](#tab:meta.unary.prop-row-15)<br>template<class T>   struct [is_unsigned](#lib:is_unsigned "21.3.6.4 Type properties [meta.unary.prop]"); | If is_arithmetic_v<T> is true, the same result as  T(0) < T(-1);  otherwise, false |  |
| [ð](#tab:meta.unary.prop-row-16)<br>template<class T>   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)<br>template<class T>   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)<br>template<class T>   struct is_scoped_enum; | T is a scoped enumeration ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")) |  |
| [ð](#tab:meta.unary.prop-row-19)<br>template<class T, class... Args>   struct is_constructible; | For a function type T or  for a cv void type T,  is_constructible_v<T, Args...> 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)<br>template<class T>   struct is_default_constructible; | is_constructible_v<T> 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)<br>template<class T>   struct is_copy_constructible; | For a referenceable type T ([[defns.referenceable]](defns.referenceable "3.45 referenceable type")), the same result as  is_constructible_v<T, const T&>, 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)<br>template<class T>   struct is_move_constructible; | For a referenceable type T, the same result as  is_constructible_v<T, T&&>, 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)<br>template<class T, class U>   struct is_assignable; | The expression declval<T>() = declval<U>() 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)<br>Access checking is performed as if in a context  unrelated to T and U[.](#tab:meta.unary.prop-row-23-column-2-sentence-2)<br>Only the validity of the immediate context  of the assignment expression is considered[.](#tab:meta.unary.prop-row-23-column-2-sentence-3)<br>[*Note [3](#tab:meta.unary.prop-row-23-column-2-note-3)*:<br>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)<br>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)<br>template<class T>   struct is_copy_assignable; | For a referenceable type T, the same result as  is_assignable_v<T&, const T&>, 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)<br>template<class T>   struct is_move_assignable; | For a referenceable type T, the same result as  is_assignable_v<T&, T&&>, 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)<br>template<class T, class U>   struct is_swappable_with; | The expressions swap(declval<T>(), declval<U>()) and  swap(declval<U>(), declval<T>()) 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)<br>Access checking is performed as if in a context  unrelated to T and U[.](#tab:meta.unary.prop-row-26-column-2-sentence-2)<br>Only the validity of the immediate context  of the swap expressions is considered[.](#tab:meta.unary.prop-row-26-column-2-sentence-3)<br>[*Note [4](#tab:meta.unary.prop-row-26-column-2-note-4)*:<br>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)<br>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)<br>template<class T>   struct is_swappable; | For a referenceable type T,  the same result as is_swappable_with_v<T&, T&>,  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)<br>template<class T>   struct is_destructible; | Either T is a reference type,  or T is a complete object type  for which the expression  declval<U&>().~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<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)<br>template<class T, class... Args>   struct   is_trivially_constructible; | is_constructible_v<T,   Args...> 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)<br>template<class T>   struct is_trivially_default_constructible; | is_trivially_constructible_v<T> 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)<br>template<class T>   struct is_trivially_copy_constructible; | For a referenceable type T, the same result as  is_trivially_constructible_v<T, const T&>, 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)<br>template<class T>   struct is_trivially_move_constructible; | For a referenceable type T, the same result as  is_trivially_constructible_v<T, T&&>, 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)<br>template<class T, class U>   struct is_trivially_assignable; | is_assignable_v<T, U> 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)<br>template<class T>   struct is_trivially_copy_assignable; | For a referenceable type T, the same result as  is_trivially_assignable_v<T&, const T&>, 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)<br>template<class T>   struct is_trivially_move_assignable; | For a referenceable type T, the same result as  is_trivially_assignable_v<T&, T&&>, 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)<br>template<class T>   struct is_trivially_destructible; | is_destructible_v<T> is true and  remove_all_extents_t<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)<br>template<class T, class... Args>   struct is_nothrow_constructible; | is_constructible_v<T,  Args...> 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)<br>template<class T>   struct is_nothrow_default_constructible; | is_nothrow_constructible_v<T> 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)<br>template<class T>   struct is_nothrow_copy_constructible; | For a referenceable type T, the same result as  is_nothrow_constructible_v<T, const T&>, 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)<br>template<class T>   struct is_nothrow_move_constructible; | For a referenceable type T, the same result as  is_nothrow_constructible_v<T, T&&>, 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)<br>template<class T, class U>   struct is_nothrow_assignable; | is_assignable_v<T, U> 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)<br>template<class T>   struct is_nothrow_copy_assignable; | For a referenceable type T, the same result as  is_nothrow_assignable_v<T&, const T&>, 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)<br>template<class T>   struct is_nothrow_move_assignable; | For a referenceable type T, the same result as  is_nothrow_assignable_v<T&, T&&>, 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)<br>template<class T, class U>   struct is_nothrow_swappable_with; | is_swappable_with_v<T, U> is true and  each swap expression of the definition of  is_swappable_with<T, U> 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)<br>template<class T>   struct is_nothrow_swappable; | For a referenceable type T,  the same result as is_nothrow_swappable_with_v<T&, T&>,  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)<br>template<class T>   struct is_nothrow_destructible; | is_destructible_v<T> 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)<br>template<class T>   struct is_nothrow_relocatable; | is_trivially_relocatable_v<T> ||(is_nothrow_move_constructible_v<remove_all_extents_t<T>> && is_nothrow_destructible_v<remove_all_extents_t<T>>) | remove_all_extents_t<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)<br>template<class T>   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)<br>template<class T>   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)<br>template<class T>   struct has_unique_object_representations; | For an array type T, the same result as  has_unique_object_representations_v<remove_all_extents_t<T>>,  otherwise *see below*[.](#tab:meta.unary.prop-row-50-column-2-sentence-1) | remove_all_extents_t<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)<br>template<class T, class U>   struct reference_constructs_from_temporary; | T is a reference type, and  the initialization T t(*VAL*<U>); 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)<br>Access checking is performed as if in  a context unrelated to T and U[.](#tab:meta.unary.prop-row-51-column-2-sentence-2)<br>Only the validity of the immediate context of  the variable initialization is considered[.](#tab:meta.unary.prop-row-51-column-2-sentence-3)<br>[*Note [5](#tab:meta.unary.prop-row-51-column-2-note-5)*:<br>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)<br>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)<br>template<class T, class U>   struct reference_converts_from_temporary; | T is a reference type, and  the initialization T t = *VAL*<U>;  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)<br>Access checking is performed as if in  a context unrelated to T and U[.](#tab:meta.unary.prop-row-52-column-2-sentence-2)<br>Only the validity of the immediate context of  the variable initialization is considered[.](#tab:meta.unary.prop-row-52-column-2-sentence-3)<br>[*Note [6](#tab:meta.unary.prop-row-52-column-2-note-6)*:<br>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)<br>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](#6)

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

[*Example [1](#example-1)*: is_const_v<const volatile int> // true is_const_v<const int*> // false is_const_v<const int&> // false is_const_v<int[3]> // false is_const_v<const int[3]> // true â *end example*]

[7](#7)

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

[*Example [2](#example-2)*: remove_const_t<const volatile int> // volatile int remove_const_t<const int* const> // const int* remove_const_t<const int&> // const int& remove_const_t<const int[3]> // int[3] â *end example*]

[8](#8)

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

[*Example [3](#example-3)*: // Given:struct P final { };union U1 { };union U2 final { };

// the following assertions hold:static_assert(!is_final_v<int>);static_assert(is_final_v<P>);static_assert(!is_final_v<U1>);static_assert(is_final_v<U2>); â *end example*]

[9](#9)

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

The predicate condition for a template specializationis_constructible<T, Args...> shall be satisfied if and only if the
following variable definition would be well-formed for some invented variable t:

T t(declval<Args>()...);

[*Note [7](#note-7)*:

These tokens are never interpreted as a function declaration[.](#9.sentence-2)

â *end note*]

Access checking is performed as if in a context unrelated to T and any of the Args[.](#9.sentence-3)

Only the validity of the immediate context of the
variable initialization is considered[.](#9.sentence-4)

[*Note [8](#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[.](#9.sentence-5)

Such side effects are not in the
âimmediate contextâ and can result in the program being ill-formed[.](#9.sentence-6)

â *end note*]

[10](#10)

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

The predicate condition for a template specializationhas_unique_object_representations<T> shall be satisfied if and only if

- [(10.1)](#10.1)

T is trivially copyable, and

- [(10.2)](#10.2)

any two objects of type T with the same value
have the same object representation, where
  * [(10.2.1)](#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)](#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[.](#10.sentence-1)

The set of scalar types for which this condition holds isimplementation-defined[.](#10.sentence-2)

[*Note [9](#note-9)*:

If a type has padding bits, the condition does not hold;
otherwise, the condition holds true for integral types[.](#10.sentence-3)

â *end note*]
