tmp/tmpsol0qk3k/{from.md → to.md}
RENAMED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
[[basic.scope.declarative]]), called *structured binding*s. Let cv
|
| 6 |
+
denote the *cv-qualifier*s in the *decl-specifier-seq*. First, a
|
| 7 |
+
variable with a unique name `e` is introduced. If the
|
| 8 |
+
*assignment-expression* in the *initializer* has array type `A` and no
|
| 9 |
+
*ref-qualifier* is present, `e` has type cv `A` and each element is
|
| 10 |
+
copy-initialized or direct-initialized from the corresponding element of
|
| 11 |
+
the *assignment-expression* as specified by the form of the
|
| 12 |
+
*initializer*. Otherwise, `e` is defined as-if by
|
| 13 |
+
|
| 14 |
+
``` bnf
|
| 15 |
+
attribute-specifier-seqₒₚₜ decl-specifier-seq ref-qualifierₒₚₜ 'e' initializer ';'
|
| 16 |
+
```
|
| 17 |
+
|
| 18 |
+
where the declaration is never interpreted as a function declaration and
|
| 19 |
+
the parts of the declaration other than the *declarator-id* are taken
|
| 20 |
+
from the corresponding structured binding declaration. The type of the
|
| 21 |
+
*id-expression* `e` is called `E`.
|
| 22 |
+
|
| 23 |
+
[*Note 1*: `E` is never a reference type (Clause
|
| 24 |
+
[[expr]]). — *end note*]
|
| 25 |
+
|
| 26 |
+
If `E` is an array type with element type `T`, the number of elements in
|
| 27 |
+
the *identifier-list* shall be equal to the number of elements of `E`.
|
| 28 |
+
Each `v`ᵢ is the name of an lvalue that refers to the element i of the
|
| 29 |
+
array and whose type is `T`; the referenced type is `T`.
|
| 30 |
+
|
| 31 |
+
[*Note 2*: The top-level cv-qualifiers of `T` are cv. — *end note*]
|
| 32 |
+
|
| 33 |
+
[*Example 1*:
|
| 34 |
+
|
| 35 |
+
``` cpp
|
| 36 |
+
auto f() -> int(&)[2];
|
| 37 |
+
auto [ x, y ] = f(); // x and y refer to elements in a copy of the array return value
|
| 38 |
+
auto& [ xr, yr ] = f(); // xr and yr refer to elements in the array referred to by f's return value
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
— *end example*]
|
| 42 |
+
|
| 43 |
+
Otherwise, if the *qualified-id* `std::tuple_size<E>` names a complete
|
| 44 |
+
type, the expression `std::tuple_size<E>::value` shall be a well-formed
|
| 45 |
+
integral constant expression and the number of elements in the
|
| 46 |
+
*identifier-list* shall be equal to the value of that expression. The
|
| 47 |
+
*unqualified-id* `get` is looked up in the scope of `E` by class member
|
| 48 |
+
access lookup ([[basic.lookup.classref]]), and if that finds at least
|
| 49 |
+
one declaration, the initializer is `e.get<i>()`. Otherwise, the
|
| 50 |
+
initializer is `get<i>(e)`, where `get` is looked up in the associated
|
| 51 |
+
namespaces ([[basic.lookup.argdep]]). In either case, `get<i>` is
|
| 52 |
+
interpreted as a *template-id*.
|
| 53 |
+
|
| 54 |
+
[*Note 3*: Ordinary unqualified lookup ([[basic.lookup.unqual]]) is
|
| 55 |
+
not performed. — *end note*]
|
| 56 |
+
|
| 57 |
+
In either case, `e` is an lvalue if the type of the entity `e` is an
|
| 58 |
+
lvalue reference and an xvalue otherwise. Given the type `Tᵢ` designated
|
| 59 |
+
by `std::tuple_element<i, E>::type`, each `v`ᵢ is a variable of type
|
| 60 |
+
“reference to `Tᵢ`” initialized with the initializer, where the
|
| 61 |
+
reference is an lvalue reference if the initializer is an lvalue and an
|
| 62 |
+
rvalue reference otherwise; the referenced type is `Tᵢ`.
|
| 63 |
+
|
| 64 |
+
Otherwise, all of `E`’s non-static data members shall be public direct
|
| 65 |
+
members of `E` or of the same unambiguous public base class of `E`, `E`
|
| 66 |
+
shall not have an anonymous union member, and the number of elements in
|
| 67 |
+
the *identifier-list* shall be equal to the number of non-static data
|
| 68 |
+
members of `E`. Designating the non-static data members of `E` as `m`₀,
|
| 69 |
+
`m`₁, `m`₂, ... (in declaration order), each `v`ᵢ is the name of an
|
| 70 |
+
lvalue that refers to the member `m`ᵢ of `e` and whose type is cv `Tᵢ`,
|
| 71 |
+
where `Tᵢ` is the declared type of that member; the referenced type is
|
| 72 |
+
cv `Tᵢ`. The lvalue is a bit-field if that member is a bit-field.
|
| 73 |
+
|
| 74 |
+
[*Example 2*:
|
| 75 |
+
|
| 76 |
+
``` cpp
|
| 77 |
+
struct S { int x1 : 2; volatile double y1; };
|
| 78 |
+
S f();
|
| 79 |
+
const auto [ x, y ] = f();
|
| 80 |
+
```
|
| 81 |
+
|
| 82 |
+
The type of the *id-expression* `x` is “`const int`”, the type of the
|
| 83 |
+
*id-expression* `y` is “`const volatile double`”.
|
| 84 |
+
|
| 85 |
+
— *end example*]
|
| 86 |
+
|