Files
2025-10-25 03:02:53 +03:00

10 KiB
Raw Permalink Blame History

[meta.rel]

21 Metaprogramming library [meta]

21.3 Metaprogramming and type traits [type.traits]

21.3.8 Relationships between types [meta.rel]

1

#

The templates specified in Table 56 may be used to query relationships between types at compile time.

2

#

Each of these templates shall be aCpp17BinaryTypeTrait ([meta.rqmts]) with a base characteristic oftrue_type if the corresponding condition is true, otherwisefalse_type.

3

#

Let ELEMS-OF(T) be the parameter packget<N>(declval()), where N is the pack ofsize_t template arguments of the specialization ofindex_sequence denoted bymake_index_sequence<tuple_size_v<remove_reference_t>>.

Table 56 — Type relationship predicates [tab:meta.rel]

🔗
Template
Condition Comments
🔗
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 ([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 1:
Base classes that are private, protected, or ambiguous are, nonetheless, base classes. — end note]
🔗
template<class Base, class Derived> struct is_virtual_base_of;
Base is a virtual base class of Derived ([class.mi]) without regard to cv-qualifiers. If Base and Derived are non-union class types, Derived shall be a complete type.
[Note 2:
Virtual base classes that are private, protected, or ambiguous are, nonetheless, virtual base classes. — end note]
[Note 3:
A class is never a virtual base class of itself. — end note]
🔗
template<class From, class To> struct is_convertible;
see below From and To shall be complete types, cv void, or arrays of unknown bound.
🔗
template<class From, class To> struct is_nothrow_convertible;
is_convertible_v<From, To> is true and the conversion, as defined by is_convertible, is known not to throw any exceptions ([expr.unary.noexcept]) From and To shall be complete types, cv void, or arrays of unknown bound.
🔗
template<class T, class U> struct is_layout_compatible;
T and U are layout-compatible ([basic.types.general]) T and U shall be complete types, cv void, or arrays of unknown bound.
🔗
template<class Base, class Derived> struct is_pointer_interconvertible_base_of;
Derived is unambiguously derived from Base without regard to cv-qualifiers, and each object of type Derived is pointer-interconvertible ([basic.compound]) with its Base subobject, 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.
🔗
template<class Fn, class... ArgTypes> struct is_invocable;
The expression INVOKE(declval(), declval()...) ([func.require]) is well-formed when treated as an unevaluated operand ([expr.context]) Fn and all types in the template parameter pack ArgTypes shall be complete types, cv void, or arrays of unknown bound.
🔗
template<class R, class Fn, class... ArgTypes> struct is_invocable_r;
The expression INVOKE(declval(), declval()...) is well-formed when treated as an unevaluated operand Fn, R, and all types in the template parameter pack ArgTypes shall be complete types, cv void, or arrays of unknown bound.
🔗
template<class Fn, class... ArgTypes> struct is_nothrow_invocable;
is_invocable_v< Fn, ArgTypes...> is true and the expression INVOKE(declval(), declval()...) is known not to throw any exceptions ([expr.unary.noexcept]) Fn and all types in the template parameter pack ArgTypes shall be complete types, cv void, or arrays of unknown bound.
🔗
template<class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r;
is_invocable_r_v< R, Fn, ArgTypes...> is true and the expression INVOKE(declval(), declval()...) is known not to throw any exceptions ([expr.unary.noexcept]) Fn, R, and all types in the template parameter pack ArgTypes shall be complete types, cv void, or arrays of unknown bound.
🔗
template<class Fn, class Tuple> struct is_applicable;
tuple-like is true and the expression INVOKE(declval(), ELEMS-OF(Tuple)...) is well-formed when treated as an unevaluated operand. Fn and Tuple shall be complete types, cv void, or arrays of unknown bound.
🔗
template<class Fn, class Tuple> struct is_nothrow_applicable;
is_applicable_v< Fn, Tuple> is true and the expression INVOKE(declval(), ELEMS-OF(Tuple)...) is known not to throw any exceptions ([expr.unary.noexcept]). Fn and Tuple shall be complete types, cv void, or arrays of unknown bound.

4

#

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

5

#

[Example 1: 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]

6

#

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();}

[Note 4:

This requirement gives well-defined results for reference types, array types, function types, and cv void.

— end note]

Access checking is performed in a context unrelated to To and From.

Only the validity of the immediate context of the expression of the return statement ([stmt.return]) (including initialization of the returned object or reference) is considered.

[Note 5:

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]