Files
cppdraft_translate/cppdraft/meta/rel.md
2025-10-25 03:02:53 +03:00

96 lines
10 KiB
Markdown
Raw 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*]