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

96 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[meta.rel]
# 21 Metaprogramming library [[meta]](./#meta)
## 21.3 Metaprogramming and type traits [[type.traits]](type.traits#meta.rel)
### 21.3.8 Relationships between types [meta.rel]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1744)
The templates specified in Table [56](#tab:meta.rel "Table 56: Type relationship predicates") may be used to query relationships between types at compile time[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1748)
Each of these templates shall be a[*Cpp17BinaryTypeTrait*](meta.rqmts#:Cpp17BinaryTypeTrait "21.3.2Requirements[meta.rqmts]") ([[meta.rqmts]](meta.rqmts "21.3.2Requirements"))
with a base characteristic oftrue_type if the corresponding condition is true, otherwisefalse_type[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1755)
Let *ELEMS-OF*(T) be the parameter packget<*N*>(declval<T>()), where *N* is the pack ofsize_t template arguments of the specialization ofindex_sequence denoted bymake_index_sequence<tuple_size_v<remove_reference_t<T>>>[.](#3.sentence-1)
Table [56](#tab:meta.rel) — Type relationship predicates [[tab:meta.rel]](./tab:meta.rel)
| [🔗](#tab:meta.rel-row-1)<br>**Template** | **Condition** | **Comments** |
| --- | --- | --- |
| [🔗](#tab:meta.rel-row-2)<br>template<class T, class U> struct [is_same](#lib:is_same "21.3.8Relationships between types[meta.rel]"); | T and U name the same type with the same cv-qualifications | |
| [🔗](#tab:meta.rel-row-3)<br>template<class Base, class Derived> struct is_base_of; | Base is a base class of Derived ([[class.derived]](class.derived "11.7Derived classes")) 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[.](#tab:meta.rel-row-3-column-3-sentence-1)<br>[*Note [1](#tab:meta.rel-row-3-column-3-note-1)*:<br>Base classes that are private, protected, or ambiguous are, nonetheless, base classes[.](#tab:meta.rel-row-3-column-3-sentence-2) — *end note*] |
| [🔗](#tab:meta.rel-row-4)<br>template<class Base, class Derived> struct is_virtual_base_of; | Base is a virtual base class of Derived ([[class.mi]](class.mi "11.7.2Multiple base classes")) without regard to cv-qualifiers[.](#tab:meta.rel-row-4-column-2-sentence-1) | If Base and Derived are non-union class types, Derived shall be a complete type[.](#tab:meta.rel-row-4-column-3-sentence-1)<br>[*Note [2](#tab:meta.rel-row-4-column-3-note-2)*:<br>Virtual base classes that are private, protected, or ambiguous are, nonetheless, virtual base classes[.](#tab:meta.rel-row-4-column-3-sentence-2) — *end note*]<br>[*Note [3](#tab:meta.rel-row-4-column-3-note-3)*:<br>A class is never a virtual base class of itself[.](#tab:meta.rel-row-4-column-3-sentence-3) — *end note*] |
| [🔗](#tab:meta.rel-row-5)<br>template<class From, class To> struct is_convertible; | *see below* | From and To shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.rel-row-5-column-3-sentence-1) |
| [🔗](#tab:meta.rel-row-6)<br>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]](expr.unary.noexcept "7.6.2.7noexcept operator")) | From and To shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.rel-row-6-column-3-sentence-1) |
| [🔗](#tab:meta.rel-row-7)<br>template<class T, class U> struct is_layout_compatible; | T and U are layout-compatible ([[basic.types.general]](basic.types.general#term.layout.compatible.type "6.9.1General")) | T and U shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.rel-row-7-column-3-sentence-1) |
| [🔗](#tab:meta.rel-row-8)<br>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]](basic.compound "6.9.4Compound types")) with its Base subobject, or Base and Derived are not unions and name the same class type without regard to cv-qualifiers[.](#tab:meta.rel-row-8-column-2-sentence-1) | 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[.](#tab:meta.rel-row-8-column-3-sentence-1) |
| [🔗](#tab:meta.rel-row-9)<br>template<class Fn, class... ArgTypes> struct is_invocable; | The expression *INVOKE*(declval<Fn>(), declval<ArgTypes>()...) ([[func.require]](func.require "22.10.4Requirements")) is well-formed when treated as an unevaluated operand ([[expr.context]](expr.context#term.unevaluated.operand "7.2.3Context dependence")) | Fn and all types in the template parameter pack ArgTypes shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.rel-row-9-column-3-sentence-1) |
| [🔗](#tab:meta.rel-row-10)<br>template<class R, class Fn, class... ArgTypes> struct is_invocable_r; | The expression *INVOKE*<R>(declval<Fn>(), declval<ArgTypes>()...) 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[.](#tab:meta.rel-row-10-column-3-sentence-1) |
| [🔗](#tab:meta.rel-row-11)<br>template<class Fn, class... ArgTypes> struct is_nothrow_invocable; | is_invocable_v< Fn, ArgTypes...> is true and the expression *INVOKE*(declval<Fn>(), declval<ArgTypes>()...) is known not to throw any exceptions ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7noexcept operator")) | Fn and all types in the template parameter pack ArgTypes shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.rel-row-11-column-3-sentence-1) |
| [🔗](#tab:meta.rel-row-12)<br>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*<R>(declval<Fn>(), declval<ArgTypes>()...) is known not to throw any exceptions ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7noexcept operator")) | Fn, R, and all types in the template parameter pack ArgTypes shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.rel-row-12-column-3-sentence-1) |
| [🔗](#tab:meta.rel-row-13)<br>template<class Fn, class Tuple> struct is_applicable; | [*tuple-like*](tuple.like#concept:tuple-like "22.4.3Concept tuple-like[tuple.like]")<Tuple> is true and the expression *INVOKE*(declval<Fn>(), *ELEMS-OF*(Tuple)...) is well-formed when treated as an unevaluated operand[.](#tab:meta.rel-row-13-column-2-sentence-1) | Fn and Tuple shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.rel-row-13-column-3-sentence-1) |
| [🔗](#tab:meta.rel-row-14)<br>template<class Fn, class Tuple> struct is_nothrow_applicable; | is_applicable_v< Fn, Tuple> is true and the expression *INVOKE*(declval<Fn>(), *ELEMS-OF*(Tuple)...) is known not to throw any exceptions ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7noexcept operator"))[.](#tab:meta.rel-row-14-column-2-sentence-1) | Fn and Tuple shall be complete types, cv void, or arrays of unknown bound[.](#tab:meta.rel-row-14-column-3-sentence-1) |
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1908)
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.13Deprecated type traits"), [[special]](special "11.4.4Special member functions")) function call
that is not an odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) of declval in the context of the corresponding definition
notwithstanding the restrictions of [[declval]](declval "22.2.6Function template declval")[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1916)
[*Example [1](#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](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1936)
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 [4](#note-4)*:
This requirement gives well-defined results for reference types,
array types, function types, and cv void[.](#6.sentence-2)
— *end note*]
Access checking is performed
in a context unrelated to To and From[.](#6.sentence-3)
Only the validity of
the immediate context of the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") of the return statement ([[stmt.return]](stmt.return "8.8.4The return statement"))
(including initialization of the returned object or reference) is considered[.](#6.sentence-4)
[*Note [5](#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[.](#6.sentence-5)
Such
side effects are not in the “immediate context” and can result in the program
being ill-formed[.](#6.sentence-6)
— *end note*]