This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-10-26


2313. Redeclaration of structured binding reference variables

Section: 9.6  [dcl.struct.bind]     Status: CD5     Submitter: Richard Smith     Date: 2016-08-12

[Accepted as a DR at the November, 2017 meeting.]

According to the current rules for structured binding declarations, the user-defined case declares the bindings as variables of reference type. This presumably makes an example like the following valid:

   auto [a] = std::tuple<int>(0);
   extern int &&a; // ok, redeclaration, could even be in a different TU 

This seems unreasonable, especially in light of the fact that it only works for the user-defined case and not the built-in case (where the bindings are not modeled as references).

Proposed resolution (August, 2017):

Change 9.6 [dcl.struct.bind] paragraph 3 as follows:

Otherwise, if the qualified-id std::tuple_size<E> names a complete type, the expression std::tuple_size<E>::value shall 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. The unqualified-id get is looked up in the scope of E by class member access lookup (_N4868_.6.5.6 [basic.lookup.classref]), and if that finds at least one declaration, the initializer is e.get<i>(). Otherwise, the initializer is get<i>(e) where get is looked up in the associated namespaces (6.5.4 [basic.lookup.argdep]). In either case, get<i> is interpreted as a template-id. [Note: Ordinary unqualified lookup (6.5.3 [basic.lookup.unqual]) is not performed. —end note] 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 , each vi is a variable variables are introduced with unique names ri of type “reference to Ti ” initialized with the initializer (9.4.4 [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.