20 General utilities library [utilities]

20.15 Metaprogramming and type traits [meta]

20.15.4 Unary type traits [meta.unary]

This subclause contains templates that may be used to query the properties of a type at compile time.

Each of these templates shall be a UnaryTypeTrait ([meta.rqmts]) with a BaseCharacteristic of true_type if the corresponding condition is true, otherwise false_type.

20.15.4.1 Primary type categories [meta.unary.cat]

The primary type categories correspond to the descriptions given in section [basic.types] of the C++ standard.

For any given type T, the result of applying one of these templates to T and to cv T shall yield the same result.

Note: For any given type T, exactly one of the primary type categories has a value member that evaluates to true.  — end note ]

Table 40 — Primary type category predicates
TemplateConditionComments
template <class T>
struct is_void;
T is void
template <class T>
struct is_null_pointer;
T is nullptr_t ([basic.fundamental])
template <class T>
struct is_integral;
T is an integral type ([basic.fundamental])
template <class T>
struct is_floating_point;
T is a floating-point type ([basic.fundamental])
template <class T>
struct is_array;
T is an array type ([basic.compound]) of known or unknown extent Class template array ([array]) is not an array type.
template <class T>
struct is_pointer;
T is a pointer type ([basic.compound]) Includes pointers to functions but not pointers to non-static members.
template <class T>
struct is_lvalue_reference;
T is an lvalue reference type ([dcl.ref])
template <class T>
struct is_rvalue_reference;
T is an rvalue reference type ([dcl.ref])
template <class T>
struct is_member_object_pointer;
T is a pointer to non-static data member
template <class T>
struct is_member_function_pointer;
T is a pointer to non-static member function
template <class T>
struct is_enum;
T is an enumeration type ([basic.compound])
template <class T>
struct is_union;
T is a union type ([basic.compound])
template <class T>
struct is_class;
T is a non-union class type ([basic.compound])
template <class T>
struct is_function;
T is a function type ([basic.compound])

20.15.4.2 Composite type traits [meta.unary.comp]

These templates provide convenient compositions of the primary type categories, corresponding to the descriptions given in section [basic.types].

For any given type T, the result of applying one of these templates to T and to cv T shall yield the same result.

Table 41 — Composite type category predicates
TemplateConditionComments
template <class T>
struct is_reference;
T is an lvalue reference or an rvalue reference
template <class T>
struct is_arithmetic;
T is an arithmetic type ([basic.fundamental])
template <class T>
struct is_fundamental;
T is a fundamental type ([basic.fundamental])
template <class T>
struct is_object;
T is an object type ([basic.types])
template <class T>
struct is_scalar;
T is a scalar type ([basic.types])
template <class T>
struct is_compound;
T is a compound type ([basic.compound])
template <class T>
struct is_member_pointer;
T is a pointer to non-static data member or non-static member function

20.15.4.3 Type properties [meta.unary.prop]

These templates provide access to some of the more important properties of types.

It is unspecified whether the library defines any full or partial specializations of any of these templates.

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 must be a complete type.

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 ([basic.types], [special]) function call that is not an odr-use ([basic.def.odr]) of declval in the context of the corresponding definition notwithstanding the restrictions of [declval].

Table 42 — Type property predicates
TemplateConditionPreconditions
template <class T>
struct is_const;
T is const-qualified ([basic.type.qualifier])
template <class T>
struct is_volatile;
T is volatile-qualified ([basic.type.qualifier])
template <class T>
struct is_trivial;
T is a trivial type ([basic.types]) remove_all_extents_t<T> shall be a complete type or (possibly cv-qualified) void.
template <class T>
struct is_trivially_copyable;
T is a trivially copyable type ([basic.types]) remove_all_extents_t<T> shall be a complete type or (possibly cv-qualified) void.
template <class T>
struct is_standard_layout;
T is a standard-layout type ([basic.types]) remove_all_extents_t<T> shall be a complete type or (possibly cv-qualified) void.
template <class T>
struct is_pod;
T is a POD type ([basic.types]) remove_all_extents_t<T> shall be a complete type or (possibly cv-qualified) void.
template <class T>
struct is_empty;
T is a class type, but not a union type, with no non-static data members other than bit-fields of length 0, no virtual member functions, no virtual base classes, and no base class B for which is_empty_v<B> is false. If T is a non-union class type, T shall be a complete type.
template <class T>
struct is_polymorphic;
T is a polymorphic class ([class.virtual]) If T is a non-union class type, T shall be a complete type.
template <class T>
struct is_abstract;
T is an abstract class ([class.abstract]) If T is a non-union class type, T shall be a complete type.
template <class T>
struct is_final;
T is a class type marked with the class-virt-specifier final (Clause [class]). [ Note: A union is a class type that can be marked with final.  — end note ] If T is a class type, T shall be a complete type.
template <class T>
struct is_signed;
If is_arithmetic_v<T> is true, the same result as T(-1) < T(0); otherwise, false
template <class T>
struct is_unsigned;
If is_arithmetic_v<T> is true, the same result as T(0) < T(-1); otherwise, false
template <class T, class... Args>
struct is_constructible;
For a function type T or for a (possibly cv-qualified) void type T, is_constructible_v<T, Args...> is false, otherwise see below T and all types in the parameter pack Args shall be complete types, (possibly cv-qualified) void, or arrays of unknown bound.
template <class T>
struct is_default_constructible;
is_constructible_v<T> is true. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
template <class T>
struct is_copy_constructible;
For a referenceable type T ([defns.referenceable]), the same result as is_constructible_v<T, const T&>, otherwise false. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
template <class T>
struct is_move_constructible;
For a referenceable type T, the same result as is_constructible_v<T, T&&>, otherwise false. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
template <class T, class U>
struct is_assignable;
The expression declval<T>() = declval<U>() is well-formed when treated as an unevaluated operand (Clause [expr]). Access checking is performed as if in a context unrelated to T and U. Only the validity of the immediate context of the assignment expression is considered. [ Note: 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. Such side effects are not in the “immediate context” and can result in the program being ill-formed.  — end note ] T and U shall be complete types, (possibly cv-qualified) void, or arrays of unknown bound.
template <class T>
struct is_copy_assignable;
For a referenceable type T, the same result as is_assignable_v<T&, const T&>, otherwise false. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
template <class T>
struct is_move_assignable;
For a referenceable type T, the same result as is_assignable_v<T&, T&&>, otherwise false. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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 (Clause [expr]) in an overload-resolution context for swappable values ([swappable.requirements]). Access checking is performed as if in a context unrelated to T and U. Only the validity of the immediate context of the swap expressions is considered. [ Note: 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. Such side effects are not in the “immediate context” and can result in the program being ill-formed.  — end note ] T and U shall be complete types, (possibly cv-qualified) void, or arrays of unknown bound.
template <class T>
struct is_swappable;
For a referenceable type T, the same result as is_swappable_with_v<T&, T&>, otherwise false. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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 (Clause [expr]), where U is remove_all_extents<T>. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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 ( [basic.types], [special]).
T and all types in the parameter pack Args shall be complete types, (possibly cv-qualified) void, or arrays of unknown bound.
template <class T>
struct is_trivially_default_constructible;
is_trivially_constructible_v<T> is true. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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 ([basic.types], [special]). T and U shall be complete types, (possibly cv-qualified) void, or arrays of unknown bound.
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. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
template <class T>
struct is_trivially_destructible;
is_destructible_v<T> is true and the indicated destructor is known to be trivial. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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]). T and all types in the parameter pack Args shall be complete types, (possibly cv-qualified) void, or arrays of unknown bound.
template <class T>
struct is_nothrow_default_constructible;
is_nothrow_constructible_v<T> is true. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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]). T and U shall be complete types, (possibly cv-qualified) void, or arrays of unknown bound.
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. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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]). T and U shall be complete types, (possibly cv-qualified) void, or arrays of unknown bound.
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. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
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]). T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
template <class T>
struct has_virtual_destructor;
T has a virtual destructor ([class.dtor]) If T is a non-union class type, T shall be a complete type.
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. T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.

Example:

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 ]

Example:

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 ]

Example:

// Given:
struct P final { };
union U1 { };
union U2 final { };

// the following assertions hold:
static_assert(!is_final_v<int>, "Error!");
static_assert( is_final_v<P>,  "Error!");
static_assert(!is_final_v<U1>, "Error!");
static_assert( is_final_v<U2>, "Error!");

 — end example ]

The predicate condition for a template specialization is_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: These tokens are never interpreted as a function declaration.  — end note ] Access checking is performed as if in a context unrelated to T and any of the Args. Only the validity of the immediate context of the variable initialization is considered. [ Note: 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. Such side effects are not in the “immediate context” and can result in the program being ill-formed.  — end note ]

The predicate condition for a template specialization has_unique_object_representations<T> shall be satisfied if and only if:

  • T is trivially copyable, and

  • any two objects of type T with the same value have the same object representation, where 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 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.

The set of scalar types for which this condition holds is implementation-defined. [ Note: If a type has padding bits, the condition does not hold; otherwise, the condition holds true for unsigned integral types.  — end note ]