[dcl.struct.bind] (original) (raw)

9 Declarations [dcl.dcl]

9.6 Structured binding declarations [dcl.struct.bind]

First, a variable with a unique name e is introduced.

If the initializer refers to one of the names introduced by the structured binding declaration, the program is ill-formed.

If E is an array type with element type T, the number of elements in the identifier-list shall be equal to the number of elements of E.

Each v is the name of an lvalue that refers to the element i of the array and whose type is T; the referenced type is T.

[ Note

:

The top-level cv-qualifiers of T are cv.

end note

]

[ Example

:

auto f() -> int(&)[2]; auto [ x, y ] = f();
auto& [ xr, yr ] = f();

end example

]

Otherwise, if the qualified-id std​::​tuple_­size<E>names a complete class type with a member named value, the expression std​::​tuple_­size<E>​::​valueshall be a well-formed integral constant expression and the number of elements in the identifier-list shall be equal to the value of that expression.

Let i be an index prvalue of type std​::​size_­tcorresponding to .

The unqualified-id get is looked up in the scope of E by class member access lookup ([basic.lookup.classref]), and if that finds at least one declaration that is a function template whose first template parameter is a non-type parameter, the initializer ise.get<i>().

Otherwise, the initializer is get<i>(e), where get is looked up in the associated namespaces ([basic.lookup.argdep]).

In either case, get<i> is interpreted as a template-id.

In either case, e is an lvalue if the type of the entity eis an lvalue reference and an xvalue otherwise.

Given the type designated bystd​::​tuple_­element<i, E>​::​type and the type designated by either & or &&, where is an lvalue reference if the initializer is an lvalue and an rvalue reference otherwise, variables are introduced with unique names as follows:

S U r = initializer ;

Each is the name of an lvalue of type that refers to the object bound to ; the referenced type is .

Otherwise, all of E's non-static data members shall be direct members of E or of the same base class of E, well-formed when named as e.namein the context of the structured binding,E shall not have an anonymous union member, and the number of elements in the identifier-list shall be equal to the number of non-static data members of E.

Designating the non-static data members of E as, , (in declaration order), each v is the name of an lvalue that refers to the member m of e and whose type is cv , where is the declared type of that member; the referenced type is cv .

The lvalue is a bit-field if that member is a bit-field.

[ Example

:

struct S { int x1 : 2; volatile double y1; }; S f(); const auto [ x, y ] = f();

The type of the id-expression x is “const int”, the type of the id-expression y is “const volatile double”.

end example

]