96 lines
10 KiB
Markdown
96 lines
10 KiB
Markdown
[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.2 Requirements [meta.rqmts]") ([[meta.rqmts]](meta.rqmts "21.3.2 Requirements"))
|
||
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.8 Relationships 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.7 Derived 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.2 Multiple 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.7 noexcept 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.1 General")) | 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.4 Compound 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.4 Requirements")) is well-formed when treated as an unevaluated operand ([[expr.context]](expr.context#term.unevaluated.operand "7.2.3 Context 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.7 noexcept 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.7 noexcept 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.3 Concept 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.7 noexcept 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.13 Deprecated type traits"), [[special]](special "11.4.4 Special member functions")) function call
|
||
that is not an odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule")) of declval in the context of the corresponding definition
|
||
notwithstanding the restrictions of [[declval]](declval "22.2.6 Function 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.20 Comma operator [expr.comma]") of the return statement ([[stmt.return]](stmt.return "8.8.4 The 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*]
|