396 lines
32 KiB
Markdown
396 lines
32 KiB
Markdown
[meta.trans]
|
||
|
||
# 21 Metaprogramming library [[meta]](./#meta)
|
||
|
||
## 21.3 Metaprogramming and type traits [[type.traits]](type.traits#meta.trans)
|
||
|
||
### 21.3.9 Transformations between types [meta.trans]
|
||
|
||
#### [21.3.9.1](#general) General [[meta.trans.general]](meta.trans.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1966)
|
||
|
||
Subclause [meta.trans] contains templates that may be used to transform one
|
||
type to another following some predefined rule[.](#general-1.sentence-1)
|
||
|
||
[2](#general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1970)
|
||
|
||
Each of the templates in [meta.trans] shall be a[*Cpp17TransformationTrait*](meta.rqmts#:Cpp17TransformationTrait "21.3.2 Requirements [meta.rqmts]") ([[meta.rqmts]](meta.rqmts "21.3.2 Requirements"))[.](#general-2.sentence-1)
|
||
|
||
#### [21.3.9.2](#cv) Const-volatile modifications [[meta.trans.cv]](meta.trans.cv)
|
||
|
||
[1](#cv-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L1976)
|
||
|
||
The templates specified in Table [57](#tab:meta.trans.cv "Table 57: Const-volatile modifications") add or remove cv-qualifications ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers"))[.](#cv-1.sentence-1)
|
||
|
||
Table [57](#tab:meta.trans.cv) — Const-volatile modifications [[tab:meta.trans.cv]](./tab:meta.trans.cv)
|
||
|
||
| [ð](#tab:meta.trans.cv-row-1)<br>**Template** | **Comments** |
|
||
| --- | --- |
|
||
| [ð](#tab:meta.trans.cv-row-2)<br>template<class T> struct remove_const; | The member typedef type denotes the type formed by removing any top-level const-qualifier from T[.](#tab:meta.trans.cv-row-2-column-2-sentence-1)<br>[*Example [1](#tab:meta.trans.cv-row-2-column-2-example-1)*:<br>remove_const_t<const volatile int> evaluates to volatile int, whereas remove_const_t<const int*> evaluates to const int*[.](#tab:meta.trans.cv-row-2-column-2-sentence-2) â *end example*] |
|
||
| [ð](#tab:meta.trans.cv-row-3)<br>template<class T> struct remove_volatile; | The member typedef type denotes the type formed by removing any top-level volatile-qualifier from T[.](#tab:meta.trans.cv-row-3-column-2-sentence-1)<br>[*Example [2](#tab:meta.trans.cv-row-3-column-2-example-2)*:<br>remove_volatile_t<const volatile int> evaluates to const int, whereas remove_volatile_t<volatile int*> evaluates to volatile int*[.](#tab:meta.trans.cv-row-3-column-2-sentence-2) â *end example*] |
|
||
| [ð](#tab:meta.trans.cv-row-4)<br>template<class T> struct remove_cv; | The member typedef type denotes the type formed by removing any top-level cv-qualifiers from T[.](#tab:meta.trans.cv-row-4-column-2-sentence-1)<br>[*Example [3](#tab:meta.trans.cv-row-4-column-2-example-3)*:<br>remove_cv_t<const volatile int> evaluates to int, whereas remove_cv_t<const volatile int*> evaluates to const volatile int*[.](#tab:meta.trans.cv-row-4-column-2-sentence-2) â *end example*] |
|
||
| [ð](#tab:meta.trans.cv-row-5)<br>template<class T> struct add_const; | The member typedef type denotes const T[.](#tab:meta.trans.cv-row-5-column-2-sentence-1)<br>[*Note [1](#tab:meta.trans.cv-row-5-column-2-note-1)*:<br>const has no effect when T is a reference, function, or top-level const-qualified type[.](#tab:meta.trans.cv-row-5-column-2-sentence-2) â *end note*] |
|
||
| [ð](#tab:meta.trans.cv-row-6)<br>template<class T> struct add_volatile; | The member typedef type denotes volatile T[.](#tab:meta.trans.cv-row-6-column-2-sentence-1)<br>[*Note [2](#tab:meta.trans.cv-row-6-column-2-note-2)*:<br>volatile has no effect when T is a reference, function, or top-level volatile-qualified type[.](#tab:meta.trans.cv-row-6-column-2-sentence-2) â *end note*] |
|
||
| [ð](#tab:meta.trans.cv-row-7)<br>template<class T> struct add_cv; | The member typedef type denotes add_const_t<add_volatile_t<T>>[.](#tab:meta.trans.cv-row-7-column-2-sentence-1) |
|
||
|
||
#### [21.3.9.3](#ref) Reference modifications [[meta.trans.ref]](meta.trans.ref)
|
||
|
||
[1](#ref-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2054)
|
||
|
||
The templates specified in Table [58](#tab:meta.trans.ref "Table 58: Reference modifications") add or remove references[.](#ref-1.sentence-1)
|
||
|
||
Table [58](#tab:meta.trans.ref) — Reference modifications [[tab:meta.trans.ref]](./tab:meta.trans.ref)
|
||
|
||
| [ð](#tab:meta.trans.ref-row-1)<br>**Template** | **Comments** |
|
||
| --- | --- |
|
||
| [ð](#tab:meta.trans.ref-row-2)<br>template<class T> struct remove_reference; | If T has type âreference to T1â then the member typedef type denotes T1; otherwise, type denotes T[.](#tab:meta.trans.ref-row-2-column-2-sentence-1) |
|
||
| [ð](#tab:meta.trans.ref-row-3)<br>template<class T> struct add_lvalue_reference; | If T is a referenceable type ([[defns.referenceable]](defns.referenceable "3.45 referenceable type")) then the member typedef type denotes T&; otherwise, type denotes T[.](#tab:meta.trans.ref-row-3-column-2-sentence-1)<br>[*Note [1](#tab:meta.trans.ref-row-3-column-2-note-1)*:<br>This rule reflects the semantics of reference collapsing ([[dcl.ref]](dcl.ref "9.3.4.3 References"))[.](#tab:meta.trans.ref-row-3-column-2-sentence-2) â *end note*] |
|
||
| [ð](#tab:meta.trans.ref-row-4)<br>template<class T> struct add_rvalue_reference; | If T is a referenceable type then the member typedef type denotes T&&; otherwise, type denotes T[.](#tab:meta.trans.ref-row-4-column-2-sentence-1)<br>[*Note [2](#tab:meta.trans.ref-row-4-column-2-note-2)*:<br>This rule reflects the semantics of reference collapsing ([[dcl.ref]](dcl.ref "9.3.4.3 References"))[.](#tab:meta.trans.ref-row-4-column-2-sentence-2)<br>For example, when a type T is a reference type T1&, the type add_rvalue_reference_t<T> is not an rvalue reference[.](#tab:meta.trans.ref-row-4-column-2-sentence-3) â *end note*] |
|
||
|
||
#### [21.3.9.4](#sign) Sign modifications [[meta.trans.sign]](meta.trans.sign)
|
||
|
||
[1](#sign-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2101)
|
||
|
||
The templates specified in Table [59](#tab:meta.trans.sign "Table 59: Sign modifications") convert an integer type to its corresponding signed or unsigned type[.](#sign-1.sentence-1)
|
||
|
||
Table [59](#tab:meta.trans.sign) — Sign modifications [[tab:meta.trans.sign]](./tab:meta.trans.sign)
|
||
|
||
| [ð](#tab:meta.trans.sign-row-1)<br>**Template** | **Comments** |
|
||
| --- | --- |
|
||
| [ð](#tab:meta.trans.sign-row-2)<br>template<class T> struct make_signed; | If T is a (possibly cv-qualified) signed integer type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")) then the member typedef type denotes T; otherwise, if T is a (possibly cv-qualified) unsigned integer type then type denotes the corresponding signed integer type, with the same cv-qualifiers as T; otherwise, type denotes the signed integer type with smallest rank ([[conv.rank]](conv.rank "6.9.6 Conversion ranks")) for which sizeof(T) == sizeof(type), with the same cv-qualifiers as T[.](#tab:meta.trans.sign-row-2-column-2-sentence-1)<br> *Mandates*: T is an integral or enumeration type other than cv bool[.](#tab:meta.trans.sign-row-2-column-2-sentence-2) |
|
||
| [ð](#tab:meta.trans.sign-row-3)<br>template<class T> struct make_unsigned; | If T is a (possibly cv-qualified) unsigned integer type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")) then the member typedef type denotes T; otherwise, if T is a (possibly cv-qualified) signed integer type then type denotes the corresponding unsigned integer type, with the same cv-qualifiers as T; otherwise, type denotes the unsigned integer type with smallest rank ([[conv.rank]](conv.rank "6.9.6 Conversion ranks")) for which sizeof(T) == sizeof(type), with the same cv-qualifiers as T[.](#tab:meta.trans.sign-row-3-column-2-sentence-1)<br> *Mandates*: T is an integral or enumeration type other than cv bool[.](#tab:meta.trans.sign-row-3-column-2-sentence-2) |
|
||
|
||
#### [21.3.9.5](#arr) Array modifications [[meta.trans.arr]](meta.trans.arr)
|
||
|
||
[1](#arr-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2149)
|
||
|
||
The templates specified in Table [60](#tab:meta.trans.arr "Table 60: Array modifications") modify array types[.](#arr-1.sentence-1)
|
||
|
||
Table [60](#tab:meta.trans.arr) — Array modifications [[tab:meta.trans.arr]](./tab:meta.trans.arr)
|
||
|
||
| [ð](#tab:meta.trans.arr-row-1)<br>**Template** | **Comments** |
|
||
| --- | --- |
|
||
| [ð](#tab:meta.trans.arr-row-2)<br>template<class T> struct remove_extent; | If T is a type âarray of Uâ, the member typedef type denotes U, otherwise T[.](#tab:meta.trans.arr-row-2-column-2-sentence-1)<br>[*Note [1](#tab:meta.trans.arr-row-2-column-2-note-1)*:<br>For multidimensional arrays, only the first array dimension is removed[.](#tab:meta.trans.arr-row-2-column-2-sentence-2)<br>For a type âarray of const Uâ, the resulting type is const U[.](#tab:meta.trans.arr-row-2-column-2-sentence-3) â *end note*] |
|
||
| [ð](#tab:meta.trans.arr-row-3)<br>template<class T> struct remove_all_extents; | If T is âmultidimensional array of Uâ, the resulting member typedef type denotes U, otherwise T[.](#tab:meta.trans.arr-row-3-column-2-sentence-1) |
|
||
|
||
[2](#arr-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2182)
|
||
|
||
[*Example [1](#arr-example-1)*: // the following assertions hold:static_assert(is_same_v<remove_extent_t<int>, int>);static_assert(is_same_v<remove_extent_t<int[2]>, int>);static_assert(is_same_v<remove_extent_t<int[2][3]>, int[3]>);static_assert(is_same_v<remove_extent_t<int[][3]>, int[3]>); â *end example*]
|
||
|
||
[3](#arr-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2193)
|
||
|
||
[*Example [2](#arr-example-2)*: // the following assertions hold:static_assert(is_same_v<remove_all_extents_t<int>, int>);static_assert(is_same_v<remove_all_extents_t<int[2]>, int>);static_assert(is_same_v<remove_all_extents_t<int[2][3]>, int>);static_assert(is_same_v<remove_all_extents_t<int[][3]>, int>); â *end example*]
|
||
|
||
#### [21.3.9.6](#ptr) Pointer modifications [[meta.trans.ptr]](meta.trans.ptr)
|
||
|
||
[1](#ptr-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2206)
|
||
|
||
The templates specified in Table [61](#tab:meta.trans.ptr "Table 61: Pointer modifications") add or remove pointers[.](#ptr-1.sentence-1)
|
||
|
||
Table [61](#tab:meta.trans.ptr) — Pointer modifications [[tab:meta.trans.ptr]](./tab:meta.trans.ptr)
|
||
|
||
| [ð](#tab:meta.trans.ptr-row-1)<br>**Template** | **Comments** |
|
||
| --- | --- |
|
||
| [ð](#tab:meta.trans.ptr-row-2)<br>template<class T> struct remove_pointer; | If T has type â(possibly cv-qualified) pointer to T1â then the member typedef type denotes T1; otherwise, it denotes T[.](#tab:meta.trans.ptr-row-2-column-2-sentence-1) |
|
||
| [ð](#tab:meta.trans.ptr-row-3)<br>template<class T> struct add_pointer; | If T is a referenceable type ([[defns.referenceable]](defns.referenceable "3.45 referenceable type")) or a cv void type then the member typedef type denotes remove_reference_t<T>*; otherwise, type denotes T[.](#tab:meta.trans.ptr-row-3-column-2-sentence-1) |
|
||
|
||
#### [21.3.9.7](#other) Other transformations [[meta.trans.other]](meta.trans.other)
|
||
|
||
[1](#other-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2238)
|
||
|
||
The templates specified in Table [62](#tab:meta.trans.other "Table 62: Other transformations") perform other modifications of a type[.](#other-1.sentence-1)
|
||
|
||
Table [62](#tab:meta.trans.other) — Other transformations [[tab:meta.trans.other]](./tab:meta.trans.other)
|
||
|
||
| [ð](#tab:meta.trans.other-row-1)<br>**Template** | **Comments** |
|
||
| --- | --- |
|
||
| [ð](#tab:meta.trans.other-row-2)<br>template<class T> struct [type_identity](#lib:type_identity "21.3.9.7 Other transformations [meta.trans.other]"); | The member typedef type denotes T[.](#tab:meta.trans.other-row-2-column-2-sentence-1) |
|
||
| [ð](#tab:meta.trans.other-row-3)<br>template<class T> struct [remove_cvref](meta.reflection.traits#lib:remove_cvref "21.4.17 Reflection type traits [meta.reflection.traits]"); | The member typedef type denotes [remove_cv_t](meta.type.synop#lib:remove_cv_t "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<[remove_reference_t](meta.type.synop#lib:remove_reference_t "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<T>>[.](#tab:meta.trans.other-row-3-column-2-sentence-1) |
|
||
| [ð](#tab:meta.trans.other-row-4)<br>template<class T> struct [decay](meta.reflection.traits#lib:decay "21.4.17 Reflection type traits [meta.reflection.traits]"); | Let U be [remove_reference_t](meta.type.synop#lib:remove_reference_t "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<T>[.](#tab:meta.trans.other-row-4-column-2-sentence-1)<br>If [is_array_v](meta.type.synop#lib:is_array_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<U> is true, the member typedef type denotes [remove_extent_t](meta.type.synop#lib:remove_extent_t "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<U>*[.](#tab:meta.trans.other-row-4-column-2-sentence-2)<br>If [is_function_v](meta.type.synop#lib:is_function_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<U> is true, the member typedef type denotes [add_pointer_t](meta.type.synop#lib:add_pointer_t "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<U>[.](#tab:meta.trans.other-row-4-column-2-sentence-3)<br>Otherwise the member typedef type denotes [remove_cv_t](meta.type.synop#lib:remove_cv_t "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<U>[.](#tab:meta.trans.other-row-4-column-2-sentence-4)<br>[*Note [1](#tab:meta.trans.other-row-4-column-2-note-1)*:<br>This behavior is similar to the lvalue-to-rvalue ([[conv.lval]](conv.lval "7.3.2 Lvalue-to-rvalue conversion")), array-to-pointer ([[conv.array]](conv.array "7.3.3 Array-to-pointer conversion")), and function-to-pointer ([[conv.func]](conv.func "7.3.4 Function-to-pointer conversion")) conversions applied when an lvalue is used as an rvalue, but also strips cv-qualifiers from class types in order to more closely model by-value argument passing[.](#tab:meta.trans.other-row-4-column-2-sentence-5) â *end note*] |
|
||
| [ð](#tab:meta.trans.other-row-5)<br>template<bool B, class T = void> struct [enable_if](#lib:enable_if "21.3.9.7 Other transformations [meta.trans.other]"); | If B is true, the member typedef type denotes T; otherwise, there shall be no member type[.](#tab:meta.trans.other-row-5-column-2-sentence-1) |
|
||
| [ð](#tab:meta.trans.other-row-6)<br>template<bool B, class T,class F> struct [conditional](#lib:conditional "21.3.9.7 Other transformations [meta.trans.other]"); | If B is true, the member typedef type denotes T[.](#tab:meta.trans.other-row-6-column-2-sentence-1)<br>If B is false, the member typedef type denotes F[.](#tab:meta.trans.other-row-6-column-2-sentence-2) |
|
||
| [ð](#tab:meta.trans.other-row-7)<br>template<class... T> struct common_type; | Unless this trait is specialized, the member type is defined or omitted as specified below[.](#tab:meta.trans.other-row-7-column-2-sentence-1)<br>If it is omitted, there shall be no member type[.](#tab:meta.trans.other-row-7-column-2-sentence-2)<br>Each type in the template parameter pack T shall be complete, cv void, or an array of unknown bound[.](#tab:meta.trans.other-row-7-column-2-sentence-3) |
|
||
| [ð](#tab:meta.trans.other-row-8)<br>template<class, class,template<class> class,template<class> class>struct[basic_common_reference](refwrap.common.ref#lib:basic_common_reference "22.10.6.8 common_reference related specializations [refwrap.common.ref]"); | Unless this trait is specialized, there shall be no member type[.](#tab:meta.trans.other-row-8-column-2-sentence-1) |
|
||
| [ð](#tab:meta.trans.other-row-9)<br>template<class... T> struct [common_reference](meta.reflection.traits#lib:common_reference "21.4.17 Reflection type traits [meta.reflection.traits]"); | The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") type is defined or omitted as specified below[.](#tab:meta.trans.other-row-9-column-2-sentence-1)<br>Each type in the parameter pack T shall be complete or cv void[.](#tab:meta.trans.other-row-9-column-2-sentence-2) |
|
||
| [ð](#tab:meta.trans.other-row-10)<br>template<class T> struct [underlying_type](meta.reflection.traits#lib:underlying_type "21.4.17 Reflection type traits [meta.reflection.traits]"); | If T is an enumeration type, the member typedef type denotes the underlying type of T ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")); otherwise, there is no member type[.](#tab:meta.trans.other-row-10-column-2-sentence-1)<br> *Mandates*: T is not an incomplete enumeration type[.](#tab:meta.trans.other-row-10-column-2-sentence-2) |
|
||
| [ð](#tab:meta.trans.other-row-11)<br>template<class Fn, class... ArgTypes> struct [invoke_result](meta.reflection.traits#lib:invoke_result "21.4.17 Reflection type traits [meta.reflection.traits]"); | If 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")), the member typedef type denotes the type decltype(*INVOKE*(declval<Fn>(), declval<ArgTypes>()...)); otherwise, there shall be no member type[.](#tab:meta.trans.other-row-11-column-2-sentence-1)<br>Access checking is performed as if in a context unrelated to Fn and ArgTypes[.](#tab:meta.trans.other-row-11-column-2-sentence-2)<br>Only the validity of the immediate context of the expression is considered[.](#tab:meta.trans.other-row-11-column-2-sentence-3)<br>[*Note [2](#tab:meta.trans.other-row-11-column-2-note-2)*:<br>The compilation of the expression 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[.](#tab:meta.trans.other-row-11-column-2-sentence-4)<br>Such side effects are not in the âimmediate contextâ and can result in the program being ill-formed[.](#tab:meta.trans.other-row-11-column-2-sentence-5) â *end note*]<br>*Preconditions*: Fn and all types in the template parameter pack ArgTypes are complete types, cv void, or arrays of unknown bound[.](#tab:meta.trans.other-row-11-column-2-sentence-6) |
|
||
| [ð](#tab:meta.trans.other-row-12)<br>template<class Fn, class Tuple> struct [apply_result](#lib:apply_result "21.3.9.7 Other transformations [meta.trans.other]"); | If [*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)...) ([[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")), the member typedef type denotes the type decltype(*INVOKE*(declval<Fn>(), *ELEMS-OF*(Tuple)...)); otherwise, there shall be no member type[.](#tab:meta.trans.other-row-12-column-2-sentence-1)<br>Access checking is performed as if in a context unrelated to Fn and Tuple[.](#tab:meta.trans.other-row-12-column-2-sentence-2)<br>Only the validity of the immediate context of the expression is considered[.](#tab:meta.trans.other-row-12-column-2-sentence-3)<br>[*Note [3](#tab:meta.trans.other-row-12-column-2-note-3)*:<br>The compilation of the expression 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[.](#tab:meta.trans.other-row-12-column-2-sentence-4)<br>Such side effects are not in the âimmediate contextâ and can result in the program being ill-formed[.](#tab:meta.trans.other-row-12-column-2-sentence-5) â *end note*]<br>*Preconditions*: Fn and Tuple are complete types, cv void, or arrays of unknown bound[.](#tab:meta.trans.other-row-12-column-2-sentence-6) |
|
||
| [ð](#tab:meta.trans.other-row-13)<br>template<class T> struct [unwrap_reference](meta.reflection.traits#lib:unwrap_reference "21.4.17 Reflection type traits [meta.reflection.traits]"); | If T is a specialization [reference_wrapper](refwrap.general#lib:reference_wrapper "22.10.6.1 General [refwrap.general]")<X> for some type X, the member typedef type of unwrap_reference<T> denotes X&, otherwise type denotes T[.](#tab:meta.trans.other-row-13-column-2-sentence-1) |
|
||
| [ð](#tab:meta.trans.other-row-14)<br>template<class T> [unwrap_ref_decay](functional.syn#lib:unwrap_ref_decay "22.10.2 Header <functional> synopsis [functional.syn]"); | The member typedef type of unwrap_ref_decay<T> denotes the type [unwrap_reference_t](meta.type.synop#lib:unwrap_reference_t "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<[decay_t](meta.type.synop#lib:decay_t "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<T>>[.](#tab:meta.trans.other-row-14-column-2-sentence-1) |
|
||
|
||
[2](#other-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2385)
|
||
|
||
In addition to being available via inclusion
|
||
of the <type_traits> header, the templatesunwrap_reference,unwrap_ref_decay,unwrap_reference_t, andunwrap_ref_decay_t are available
|
||
when the header <functional> ([[functional.syn]](functional.syn "22.10.2 Header <functional> synopsis")) is included[.](#other-2.sentence-1)
|
||
|
||
[3](#other-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2396)
|
||
|
||
Let:
|
||
|
||
- [(3.1)](#other-3.1)
|
||
|
||
*CREF*(A) be [add_lvalue_reference_t](meta.type.synop#lib:add_lvalue_reference_t "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<const [remove_reference_t](meta.type.synop#lib:remove_reference_t "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<A>>,
|
||
|
||
- [(3.2)](#other-3.2)
|
||
|
||
*XREF*(A) denote a unary alias template T such that T<U> denotes the same type as U with the addition
|
||
of A's cv and reference qualifiers, for a non-reference cv-unqualified
|
||
type U,
|
||
|
||
- [(3.3)](#other-3.3)
|
||
|
||
*COPYCV*(FROM, TO) be an alias for type TO with the addition of FROM's top-level cv-qualifiers,
|
||
[*Example [1](#other-example-1)*:
|
||
*COPYCV*(const int, volatile short) is an alias for const volatile short[.](#other-3.3.sentence-1)
|
||
â *end example*]
|
||
|
||
- [(3.4)](#other-3.4)
|
||
|
||
*COND-RES*(X, Y) be decltype(false ? declval<X(&)()>()() : declval<Y(&)()>()())[.](#other-3.sentence-1)
|
||
|
||
Given types A and B,
|
||
let X be remove_reference_t<A>,
|
||
let Y be remove_reference_t<B>, and
|
||
let *COMMON-REF*(A, B) be:
|
||
|
||
- [(3.5)](#other-3.5)
|
||
|
||
If A and B are both lvalue reference types, *COMMON-REF*(A, B) is *COND-RES*(*COPYCV*(X, Y) &, *COPYCV*(Y, X) &) if that type exists
|
||
and is a reference type[.](#other-3.5.sentence-1)
|
||
|
||
- [(3.6)](#other-3.6)
|
||
|
||
Otherwise, let C be [remove_reference_t](meta.type.synop#lib:remove_reference_t "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<*COMMON-REF*(X&, Y&)>&&[.](#other-3.6.sentence-1)
|
||
If A and B are both rvalue reference types, C is well-formed, and [is_convertible_v](meta.type.synop#lib:is_convertible_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<A, C> && [is_convertible_v](meta.type.synop#lib:is_convertible_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<B, C> is true,
|
||
then *COMMON-REF*(A, B) is C[.](#other-3.6.sentence-2)
|
||
|
||
- [(3.7)](#other-3.7)
|
||
|
||
Otherwise, let D be *COMMON-REF*(const X&, Y&)[.](#other-3.7.sentence-1)
|
||
If A is an rvalue
|
||
reference and B is an lvalue reference and D is
|
||
well-formed and [is_convertible_v](meta.type.synop#lib:is_convertible_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<A, D> is true, then *COMMON-REF*(A, B) is D[.](#other-3.7.sentence-2)
|
||
|
||
- [(3.8)](#other-3.8)
|
||
|
||
Otherwise, if A is an lvalue reference and B is an rvalue reference, then *COMMON-REF*(A, B) is *COMMON-REF*(B, A)[.](#other-3.8.sentence-1)
|
||
|
||
- [(3.9)](#other-3.9)
|
||
|
||
Otherwise, *COMMON-REF*(A, B) is ill-formed[.](#other-3.9.sentence-1)
|
||
|
||
If any of the types computed above is ill-formed, then*COMMON-REF*(A, B) is ill-formed[.](#other-3.sentence-3)
|
||
|
||
[4](#other-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2444)
|
||
|
||
For the common_type trait applied to a template parameter pack T of types,
|
||
the member type shall be either defined or not present as follows:
|
||
|
||
- [(4.1)](#other-4.1)
|
||
|
||
If sizeof...(T) is zero, there shall be no member type[.](#other-4.1.sentence-1)
|
||
|
||
- [(4.2)](#other-4.2)
|
||
|
||
If sizeof...(T) is one, let T0 denote the sole type
|
||
constituting the pack T[.](#other-4.2.sentence-1)
|
||
The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") type shall denote the same
|
||
type, if any, as common_type_t<T0, T0>;
|
||
otherwise there shall be no member type[.](#other-4.2.sentence-2)
|
||
|
||
- [(4.3)](#other-4.3)
|
||
|
||
If sizeof...(T) is two,
|
||
let the first and second types constituting T be denoted
|
||
by T1 and T2, respectively, and
|
||
let D1 and D2 denote
|
||
the same types as decay_t<T1> and decay_t<T2>, respectively[.](#other-4.3.sentence-1)
|
||
|
||
* [(4.3.1)](#other-4.3.1)
|
||
|
||
If is_same_v<T1, D1> is false or is_same_v<T2, D2> is false,
|
||
let C denote the same type, if any,
|
||
as common_type_t<D1, D2>[.](#other-4.3.1.sentence-1)
|
||
|
||
* [(4.3.2)](#other-4.3.2)
|
||
|
||
[*Note [4](#other-note-4)*:
|
||
None of the following will apply if there is a specialization common_type<D1, D2>[.](#other-4.3.2.sentence-1)
|
||
â *end note*]
|
||
|
||
* [(4.3.3)](#other-4.3.3)
|
||
|
||
Otherwise, ifdecay_t<decltype(false ? declval<D1>() : declval<D2>())> denotes a valid type, let C denote that type[.](#other-4.3.3.sentence-1)
|
||
|
||
* [(4.3.4)](#other-4.3.4)
|
||
|
||
Otherwise, if *COND-RES*(*CREF*(D1), *CREF*(D2)) denotes a type, let C denote the type decay_t<*COND-RES*(*CREF*(D1), *CREF*(D2))>[.](#other-4.3.4.sentence-1)
|
||
|
||
In either case, the member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") type shall denote
|
||
the same type, if any, as C[.](#other-4.3.sentence-2)
|
||
Otherwise, there shall be no member type[.](#other-4.3.sentence-3)
|
||
|
||
- [(4.4)](#other-4.4)
|
||
|
||
If sizeof...(T) is greater than two,
|
||
let T1, T2, and R, respectively,
|
||
denote the first, second, and (pack of) remaining types constituting T[.](#other-4.4.sentence-1)
|
||
Let C denote the same type, if any, as common_type_t<T1, T2>[.](#other-4.4.sentence-2)
|
||
If there is such a type C, the member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") type shall denote the same type, if any, as common_type_t<C, R...>[.](#other-4.4.sentence-3)
|
||
Otherwise, there shall be no member type[.](#other-4.4.sentence-4)
|
||
|
||
[5](#other-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2496)
|
||
|
||
Notwithstanding the provisions of [[meta.rqmts]](meta.rqmts "21.3.2 Requirements"), and
|
||
pursuant to [[namespace.std]](namespace.std "16.4.5.2.1 Namespace std"),
|
||
a program may specialize common_type<T1, T2> for types T1 and T2 such thatis_same_v<T1, decay_t<T1>> andis_same_v<T2, decay_t<T2>> are each true[.](#other-5.sentence-1)
|
||
|
||
[*Note [5](#other-note-5)*:
|
||
|
||
Such specializations are needed when only explicit conversions
|
||
are desired between the template arguments[.](#other-5.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
Such a specialization need not have a member named type,
|
||
but if it does,
|
||
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") common_type<T1, T2>::type shall denote
|
||
a cv-unqualified non-reference type
|
||
to which each of the types T1 and T2 is explicitly convertible[.](#other-5.sentence-3)
|
||
|
||
Moreover, common_type_t<T1, T2> shall denote
|
||
the same type, if any, as does common_type_t<T2, T1>[.](#other-5.sentence-4)
|
||
|
||
No diagnostic is required for a violation of this Note's rules[.](#other-5.sentence-5)
|
||
|
||
[6](#other-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2516)
|
||
|
||
For the common_reference trait applied to a parameter packT of types, the member type shall be either defined or not
|
||
present as follows:
|
||
|
||
- [(6.1)](#other-6.1)
|
||
|
||
If sizeof...(T) is zero, there shall be no member type[.](#other-6.1.sentence-1)
|
||
|
||
- [(6.2)](#other-6.2)
|
||
|
||
Otherwise, if sizeof...(T) is one, let T0 denote the sole
|
||
type in the pack T[.](#other-6.2.sentence-1)
|
||
The member typedef type shall denote the
|
||
same type as T0[.](#other-6.2.sentence-2)
|
||
|
||
- [(6.3)](#other-6.3)
|
||
|
||
Otherwise, if sizeof...(T) is two, let T1 and T2 denote the two types in the pack T[.](#other-6.3.sentence-1)
|
||
Then
|
||
* [(6.3.1)](#other-6.3.1)
|
||
|
||
Let R be *COMMON-REF*(T1, T2)[.](#other-6.3.1.sentence-1)
|
||
If T1 and T2 are reference types, R is well-formed, and is_convertible_v<add_pointer_t<T1>, add_pointer_t<R>> && is_convertible_v<add_pointer_t<T2>, add_pointer_t<R>> is true,
|
||
then the member typedef type denotes R[.](#other-6.3.1.sentence-2)
|
||
|
||
* [(6.3.2)](#other-6.3.2)
|
||
|
||
Otherwise, if basic_common_reference<remove_cvref_t<T1>, remove_cvref_t<T2>,
|
||
*XREF*(T1), *XREF*(T2)>::type is well-formed, then the member typedef type denotes that type[.](#other-6.3.2.sentence-1)
|
||
|
||
* [(6.3.3)](#other-6.3.3)
|
||
|
||
Otherwise, if *COND-RES*(T1, T2) is well-formed,
|
||
then the member typedef type denotes that type[.](#other-6.3.3.sentence-1)
|
||
|
||
* [(6.3.4)](#other-6.3.4)
|
||
|
||
Otherwise, if common_type_t<T1, T2> is well-formed, then the
|
||
member typedef type denotes that type[.](#other-6.3.4.sentence-1)
|
||
|
||
* [(6.3.5)](#other-6.3.5)
|
||
|
||
Otherwise, there shall be no member type[.](#other-6.3.5.sentence-1)
|
||
|
||
- [(6.4)](#other-6.4)
|
||
|
||
Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest, respectively, denote the first, second, and
|
||
(pack of) remaining types comprising T[.](#other-6.4.sentence-1)
|
||
Let C be the type common_reference_t<T1, T2>[.](#other-6.4.sentence-2)
|
||
Then:
|
||
* [(6.4.1)](#other-6.4.1)
|
||
|
||
If there is such a type C, the member typedef type shall
|
||
denote the same type, if any, as common_reference_t<C, Rest...>[.](#other-6.4.1.sentence-1)
|
||
|
||
* [(6.4.2)](#other-6.4.2)
|
||
|
||
Otherwise, there shall be no member type[.](#other-6.4.2.sentence-1)
|
||
|
||
[7](#other-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2562)
|
||
|
||
Notwithstanding the provisions of [[meta.rqmts]](meta.rqmts "21.3.2 Requirements"), and
|
||
pursuant to [[namespace.std]](namespace.std "16.4.5.2.1 Namespace std"), a program may partially specializebasic_common_reference<T, U, TQual, UQual> for types T and U such thatis_same_v<T, decay_t<T>> andis_same_v<U, decay_t<U>> are each true[.](#other-7.sentence-1)
|
||
|
||
[*Note [6](#other-note-6)*:
|
||
|
||
Such specializations
|
||
can be used to influence the result of common_reference, and
|
||
are needed when only explicit conversions are desired
|
||
between the template arguments[.](#other-7.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
Such a specialization need not have a member named type, but if it does,
|
||
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]")basic_common_reference<T, U, TQual, UQual>::type shall denote a type
|
||
to which each of the types TQual<T> andUQual<U> is convertible[.](#other-7.sentence-3)
|
||
|
||
Moreover, basic_common_reference<T, U, TQual, UQual>::type shall denote
|
||
the same type, if any, as doesbasic_common_reference<U, T, UQual, TQual>::type[.](#other-7.sentence-4)
|
||
|
||
No diagnostic is required for a violation of these rules[.](#other-7.sentence-5)
|
||
|
||
[8](#other-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2586)
|
||
|
||
[*Example [2](#other-example-2)*:
|
||
|
||
Given these definitions:using PF1 = bool (&)();using PF2 = short (*)(long);
|
||
|
||
struct S {operator PF2() const; double operator()(char, int&); void fn(long) const; char data;};
|
||
|
||
using PMF = void (S::*)(long) const;using PMD = char S::*; the following assertions will hold:static_assert(is_same_v<invoke_result_t<S, int>, short>);static_assert(is_same_v<invoke_result_t<S&, unsigned char, int&>, double>);static_assert(is_same_v<invoke_result_t<PF1>, bool>);static_assert(is_same_v<invoke_result_t<PMF, unique_ptr<S>, int>, void>);static_assert(is_same_v<invoke_result_t<PMD, S>, char&&>);static_assert(is_same_v<invoke_result_t<PMD, const S*>, const char&>);
|
||
|
||
â *end example*]
|