20 General utilities library [utilities]

20.15 Metaprogramming and type traits [meta]

20.15.6 Relationships between types [meta.rel]

This subclause contains templates that may be used to query relationships between types at compile time.

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

Table 44 — Type relationship predicates
TemplateConditionComments
template <class T, class U>
struct is_same;
T and U name the same type with the same cv-qualifications
template <class Base, class Derived>
struct is_base_of;
Base is a base class of Derived (Clause [class.derived]) without regard to cv-qualifiers or Base and Derived are not unions and name the same class type without regard to cv-qualifiers If Base and Derived are non-union class types and are not possibly cv-qualified versions of the same type, Derived shall be a complete type. [ Note: Base classes that are private, protected, or ambiguous are, nonetheless, base classes.  — end note ]
template <class From, class To>
struct is_convertible;
see below From and To shall be complete types, arrays of unknown bound, or (possibly cv-qualified) void types.
template <class Fn, class... ArgTypes, class R>
struct is_callable<
Fn(ArgTypes...), R>;
The expression INVOKE(declval<Fn>(), declval<ArgTypes>()..., R) is well formed when treated as an unevaluated operand Fn, R, and all types in the parameter pack ArgTypes shall be complete types, (possibly cv-qualified) void, or arrays of unknown bound.
template <class Fn, class... ArgTypes, class R>
struct is_nothrow_callable<
Fn(ArgTypes...), R>;
is_callable_v<
Fn(ArgTypes...), R> is true and the expression INVOKE(declval<Fn>(), declval<ArgTypes>()..., R) is known not to throw any exceptions
Fn, R, and all types in the parameter pack ArgTypes shall be complete types, (possibly cv-qualified) void, or arrays of unknown bound.

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].

Example:

struct B {};
struct B1 : B {};
struct B2 : B {};
struct D : private B1, private B2 {};

is_base_of_v<B, D>         // true
is_base_of_v<const B, D>   // true
is_base_of_v<B, const D>   // true
is_base_of_v<B, const B>   // true
is_base_of_v<D, B>         // false
is_base_of_v<B&, D&>       // false
is_base_of_v<B[3], D[3]>   // false
is_base_of_v<int, int>     // false

 — end example ]

The predicate condition for a template specialization is_convertible<From, To> shall be satisfied if and only if the return expression in the following code would be well-formed, including any implicit conversions to the return type of the function:

To test() {
  return declval<From>();
}

Note: This requirement gives well defined results for reference types, void types, array types, and function types. — end note ] Access checking is performed as if in a context unrelated to To and From. Only the validity of the immediate context of the expression of the return-statement (including conversions to the return type) is considered. [ Note: The evaluation of the conversion 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 ]