tmp/tmpl2_xlot5/{from.md → to.md}
RENAMED
|
@@ -1,16 +1,21 @@
|
|
| 1 |
## Structured binding declarations <a id="dcl.struct.bind">[[dcl.struct.bind]]</a>
|
| 2 |
|
| 3 |
A structured binding declaration introduces the *identifier*s `v₀`,
|
| 4 |
-
`v₁`, `v₂`, … of the *identifier-list* as names
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
*
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
*
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
``` bnf
|
| 14 |
attribute-specifier-seqₒₚₜ *S* cv 'A' e ';'
|
| 15 |
```
|
| 16 |
|
|
@@ -27,44 +32,94 @@ the parts of the declaration other than the *declarator-id* are taken
|
|
| 27 |
from the corresponding structured binding declaration. The type of the
|
| 28 |
*id-expression* *`e`* is called `E`.
|
| 29 |
|
| 30 |
[*Note 1*: `E` is never a reference type [[expr.prop]]. — *end note*]
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
If the *initializer* refers to one of the names introduced by the
|
| 33 |
structured binding declaration, the program is ill-formed.
|
| 34 |
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
|
|
|
| 39 |
|
| 40 |
-
[*Note
|
| 41 |
|
| 42 |
-
[*Example
|
| 43 |
|
| 44 |
``` cpp
|
| 45 |
auto f() -> int(&)[2];
|
| 46 |
auto [ x, y ] = f(); // x and y refer to elements in a copy of the array return value
|
| 47 |
auto& [ xr, yr ] = f(); // xr and yr refer to elements in the array referred to by f's return value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
```
|
| 49 |
|
| 50 |
— *end example*]
|
| 51 |
|
| 52 |
Otherwise, if the *qualified-id* `std::tuple_size<E>` names a complete
|
| 53 |
class type with a member named `value`, the expression
|
| 54 |
`std::tuple_size<E>::value` shall be a well-formed integral constant
|
| 55 |
-
expression and the
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
|
| 65 |
-
[*Note
|
| 66 |
performed. — *end note*]
|
| 67 |
|
| 68 |
In either case, *`e`* is an lvalue if the type of the entity *`e`* is an
|
| 69 |
lvalue reference and an xvalue otherwise. Given the type `Tᵢ` designated
|
| 70 |
by `std::tuple_element<i, E>::type` and the type `Uᵢ` designated by
|
|
@@ -74,26 +129,30 @@ are introduced with unique names `rᵢ` as follows:
|
|
| 74 |
|
| 75 |
``` bnf
|
| 76 |
*S* 'Uᵢ rᵢ =' initializer ';'
|
| 77 |
```
|
| 78 |
|
| 79 |
-
Each
|
| 80 |
-
object bound to `rᵢ`; the referenced type is `Tᵢ`.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
Otherwise, all of `E`’s non-static data members shall be direct members
|
| 83 |
of `E` or of the same base class of `E`, well-formed when named as
|
| 84 |
`e.name` in the context of the structured binding, `E` shall not have an
|
| 85 |
-
anonymous union member, and the
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
type
|
| 92 |
-
|
| 93 |
|
| 94 |
-
[*Example
|
| 95 |
|
| 96 |
``` cpp
|
| 97 |
struct S { mutable int x1 : 2; volatile double y1; };
|
| 98 |
S f();
|
| 99 |
const auto [ x, y ] = f();
|
|
|
|
| 1 |
## Structured binding declarations <a id="dcl.struct.bind">[[dcl.struct.bind]]</a>
|
| 2 |
|
| 3 |
A structured binding declaration introduces the *identifier*s `v₀`,
|
| 4 |
+
`v₁`, `v₂`, …, `v_N-1` of the *sb-identifier-list* as names. An
|
| 5 |
+
*sb-identifier* that contains an ellipsis introduces a structured
|
| 6 |
+
binding pack [[temp.variadic]]. A *structured binding* is either an
|
| 7 |
+
*sb-identifier* that does not contain an ellipsis or an element of a
|
| 8 |
+
structured binding pack. The optional *attribute-specifier-seq* of an
|
| 9 |
+
*sb-identifier* appertains to the associated structured bindings. Let cv
|
| 10 |
+
denote the *cv-qualifier*s in the *decl-specifier-seq* and *S* consist
|
| 11 |
+
of each *decl-specifier* of the *decl-specifier-seq* that is
|
| 12 |
+
`constexpr`, `constinit`, or a *storage-class-specifier*. A cv that
|
| 13 |
+
includes `volatile` is deprecated; see [[depr.volatile.type]]. First, a
|
| 14 |
+
variable with a unique name *`e`* is introduced. If the
|
| 15 |
+
*assignment-expression* in the *initializer* has array type *cv1* `A`
|
| 16 |
+
and no *ref-qualifier* is present, *`e`* is defined by
|
| 17 |
|
| 18 |
``` bnf
|
| 19 |
attribute-specifier-seqₒₚₜ *S* cv 'A' e ';'
|
| 20 |
```
|
| 21 |
|
|
|
|
| 32 |
from the corresponding structured binding declaration. The type of the
|
| 33 |
*id-expression* *`e`* is called `E`.
|
| 34 |
|
| 35 |
[*Note 1*: `E` is never a reference type [[expr.prop]]. — *end note*]
|
| 36 |
|
| 37 |
+
The *structured binding size* of `E`, as defined below, is the number of
|
| 38 |
+
structured bindings that need to be introduced by the structured binding
|
| 39 |
+
declaration. If there is no structured binding pack, then the number of
|
| 40 |
+
elements in the *sb-identifier-list* shall be equal to the structured
|
| 41 |
+
binding size of `E`. Otherwise, the number of non-pack elements shall be
|
| 42 |
+
no more than the structured binding size of `E`; the number of elements
|
| 43 |
+
of the structured binding pack is the structured binding size of `E`
|
| 44 |
+
less the number of non-pack elements in the *sb-identifier-list*.
|
| 45 |
+
|
| 46 |
+
Let $\textrm{SB}_i$ denote the $i^\textrm{th}$ structured binding in the
|
| 47 |
+
structured binding declaration after expanding the structured binding
|
| 48 |
+
pack, if any.
|
| 49 |
+
|
| 50 |
+
[*Note 2*: If there is no structured binding pack, then $\textrm{SB}_i$
|
| 51 |
+
denotes `vᵢ`. — *end note*]
|
| 52 |
+
|
| 53 |
+
[*Example 1*:
|
| 54 |
+
|
| 55 |
+
``` cpp
|
| 56 |
+
struct C { int x, y, z; };
|
| 57 |
+
|
| 58 |
+
template<class T>
|
| 59 |
+
void now_i_know_my() {
|
| 60 |
+
auto [a, b, c] = C(); // OK, $SB_0$ is a, $SB_1$ is b, and $SB_2$ is c
|
| 61 |
+
auto [d, ...e] = C(); // OK, $SB_0$ is d, the pack e (`v`_1) contains two structured bindings: $SB_1$ and $SB_2$
|
| 62 |
+
auto [...f, g] = C(); // OK, the pack f (`v`_0) contains two structured bindings: $SB_0$ and $SB_1$, and $SB_2$ is g
|
| 63 |
+
auto [h, i, j, ...k] = C(); // OK, the pack k is empty
|
| 64 |
+
auto [l, m, n, o, ...p] = C(); // error: structured binding size is too small
|
| 65 |
+
}
|
| 66 |
+
```
|
| 67 |
+
|
| 68 |
+
— *end example*]
|
| 69 |
+
|
| 70 |
+
If a structured binding declaration appears as a *condition*, the
|
| 71 |
+
decision variable [[stmt.pre]] of the condition is *`e`*.
|
| 72 |
+
|
| 73 |
If the *initializer* refers to one of the names introduced by the
|
| 74 |
structured binding declaration, the program is ill-formed.
|
| 75 |
|
| 76 |
+
`E` shall not be an array type of unknown bound. If `E` is any other
|
| 77 |
+
array type with element type `T`, the structured binding size of `E` is
|
| 78 |
+
equal to the number of elements of `E`. Each $\textrm{SB}_i$ is the name
|
| 79 |
+
of an lvalue that refers to the element i of the array and whose type is
|
| 80 |
+
`T`; the referenced type is `T`.
|
| 81 |
|
| 82 |
+
[*Note 3*: The top-level cv-qualifiers of `T` are cv. — *end note*]
|
| 83 |
|
| 84 |
+
[*Example 2*:
|
| 85 |
|
| 86 |
``` cpp
|
| 87 |
auto f() -> int(&)[2];
|
| 88 |
auto [ x, y ] = f(); // x and y refer to elements in a copy of the array return value
|
| 89 |
auto& [ xr, yr ] = f(); // xr and yr refer to elements in the array referred to by f's return value
|
| 90 |
+
|
| 91 |
+
auto g() -> int(&)[4];
|
| 92 |
+
|
| 93 |
+
template<size_t N>
|
| 94 |
+
void h(int (&arr)[N]) {
|
| 95 |
+
auto [a, ...b, c] = arr; // a names the first element of the array, b is a pack referring to the second and
|
| 96 |
+
// third elements, and c names the fourth element
|
| 97 |
+
auto& [...e] = arr; // e is a pack referring to the four elements of the array
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
void call_h() {
|
| 101 |
+
h(g());
|
| 102 |
+
}
|
| 103 |
```
|
| 104 |
|
| 105 |
— *end example*]
|
| 106 |
|
| 107 |
Otherwise, if the *qualified-id* `std::tuple_size<E>` names a complete
|
| 108 |
class type with a member named `value`, the expression
|
| 109 |
`std::tuple_size<E>::value` shall be a well-formed integral constant
|
| 110 |
+
expression and the structured binding size of `E` is equal to the value
|
| 111 |
+
of that expression. Let `i` be an index prvalue of type `std::size_t`
|
| 112 |
+
corresponding to `vᵢ`. If a search for the name `get` in the scope of
|
| 113 |
+
`E` [[class.member.lookup]] finds at least one declaration that is a
|
| 114 |
+
function template whose first template parameter is a constant template
|
| 115 |
+
parameter, the initializer is `e.get<i>()`. Otherwise, the initializer
|
| 116 |
+
is `get<i>(e)`, where `get` undergoes argument-dependent lookup
|
| 117 |
+
[[basic.lookup.argdep]]. In either case, `get<i>` is interpreted as a
|
| 118 |
+
*template-id*.
|
| 119 |
|
| 120 |
+
[*Note 4*: Ordinary unqualified lookup [[basic.lookup.unqual]] is not
|
| 121 |
performed. — *end note*]
|
| 122 |
|
| 123 |
In either case, *`e`* is an lvalue if the type of the entity *`e`* is an
|
| 124 |
lvalue reference and an xvalue otherwise. Given the type `Tᵢ` designated
|
| 125 |
by `std::tuple_element<i, E>::type` and the type `Uᵢ` designated by
|
|
|
|
| 129 |
|
| 130 |
``` bnf
|
| 131 |
*S* 'Uᵢ rᵢ =' initializer ';'
|
| 132 |
```
|
| 133 |
|
| 134 |
+
Each $\textrm{SB}_i$ is the name of an lvalue of type `Tᵢ` that refers
|
| 135 |
+
to the object bound to `rᵢ`; the referenced type is `Tᵢ`. The
|
| 136 |
+
initialization of *`e`* and any conversion of *`e`* considered as a
|
| 137 |
+
decision variable [[stmt.pre]] is sequenced before the initialization of
|
| 138 |
+
any `rᵢ`. The initialization of each `rᵢ` is sequenced before the
|
| 139 |
+
initialization of any `rⱼ` where i < j.
|
| 140 |
|
| 141 |
Otherwise, all of `E`’s non-static data members shall be direct members
|
| 142 |
of `E` or of the same base class of `E`, well-formed when named as
|
| 143 |
`e.name` in the context of the structured binding, `E` shall not have an
|
| 144 |
+
anonymous union member, and the structured binding size of `E` is equal
|
| 145 |
+
to the number of non-static data members of `E`. Designating the
|
| 146 |
+
non-static data members of `E` as `m₀`, `m₁`, `m₂`, … (in declaration
|
| 147 |
+
order), each $\textrm{SB}_i$ is the name of an lvalue that refers to the
|
| 148 |
+
member `m`ᵢ of *`e`* and whose type is that of `e.mᵢ` [[expr.ref]]; the
|
| 149 |
+
referenced type is the declared type of `mᵢ` if that type is a reference
|
| 150 |
+
type, or the type of `e.mᵢ` otherwise. The lvalue is a bit-field if that
|
| 151 |
+
member is a bit-field.
|
| 152 |
|
| 153 |
+
[*Example 3*:
|
| 154 |
|
| 155 |
``` cpp
|
| 156 |
struct S { mutable int x1 : 2; volatile double y1; };
|
| 157 |
S f();
|
| 158 |
const auto [ x, y ] = f();
|