auto f() -> int(&);
auto [ x, y ] = f(); // x and y refer to elements in a copy of the array return value
auto& [ xr, yr ] = f(); // xr and yr refer to elements in the array referred to by f's return value
names a complete type,
the expression std::tuple_size<E>::value
shall be a well-formed integral constant expression
the number of elements in
the identifier-list shall be equal to the value of that
The unqualified-idget 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 is
In either case, e is an lvalue if the type of the entity e
is an lvalue reference and an xvalue otherwise.
Given the type Ti
designated by std::tuple_element<i, E>::type,
variables are introduced with unique names ri
of type “reference to Ti”
initialized with the initializer ([dcl.init.ref]),
where the reference is an lvalue reference if the initializer is
an lvalue and an rvalue reference otherwise.
Each vi is the name of an lvalue of type Ti
that refers to the object bound to ri;
the referenced type is Ti.
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.name
in 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
m0, m1, m2, .