for-range-declaration:
      attribute-specifier-seqopt decl-specifier-seq declarator
      attribute-specifier-seqopt decl-specifier-seq &opt { identifier-list }
In section 7 [dcl.dcl] paragraph 1, change the grammar to allow a
decomposition declaration:
simple-declaration:
      decl-specifier-seq init-declarator-listopt ;
      attribute-specifier-seq decl-specifier-seq init-declarator-list ;
      attribute-specifier-seqopt decl-specifier-seq &opt { identifier-list } brace-or-equal-initializer ;
Add a new paragraph after 7 [dcl.dcl] paragraph 8:
A simple-declaration with an identifier-list is called a decomposition declaration. The decl-specifier-seq shall contain only the type-specifierAdd after 7.1.6.4 [dcl.spec.auto] paragraph 8:auto(7.1.6.4 [dcl.spec.auto]) and cv-qualifiers. The brace-or-equal-initializer shall be of the form "= assignment-expression" or of the form "{ assignment-expression }". If the assignment-expression is a prvalue, the decl-specifier-seq does not contain the cv-qualifierconst, and&follows the decl-specifier-seq, the program is ill-formed.
A decomposition declaration introduces the identifiers of the identifier-list as variable names in the order of appearance, with types deduced from the initializer. If the assignment-expression of the decomposition declaration has scalar type, the identifier-list shall contain a single identifier and a single variable is introduced as if byattribute-specifier-seqopt decl-specifier-seq &opt identifier brace-or-equal-initializer ;If the assignment-expression has union type, the program is ill-formed.Otherwise, i.e. the assignment-expression has non-union class or array type
E, let e be a glvalue of typeE.The expression getn is defined as follows:
- If the assignment-expression is a prvalue, e is an xvalue that designates a temporary object copy-initialized from the assignment-expression. The lifetime of the temporary ends immediately after the last variable declaration (see below) if no
&follows the decl-specifier-seq in the decomposition declaration, and is extended as usual (12.2 [class.temporary] otherwise.- Otherwise, e refers to the result of evaluating the assignment-expression and has its value category.
If
- If E is an array type, getn is e[n].
- If E is a class type, the unqualified-id
getis looked up in the scope of E as if by class member access lookup (3.4.5 [basic.lookup.classref]), and if that finds at least one declaration, getn ise.get<n>().- Otherwise, getn is
get<n>(e), wheregetis looked up in the associated namespaces (3.4.2 [basic.lookup.argdep]). [ Note: Ordinary unqualified lookup (3.4.1 [basic.lookup.unqual]) is not performed. -- end note ]Eis an array type, the number of identifiers shall be equal to the number of elements ofE. Otherwise, if the expression get0 is not well-formed, all ofE's non-static data members and bit-fields shall be public direct members ofEor of the same public base class ofE,Eshall not have an anonymous union member, and the number of identifiers in the identifier-list shall be equal to the number of non-static data members ofE.For the i-th identifier vi in the identifier-list, where numbering starts at 1, a variable is declared using the attribute-specifier-seq and decl-specifier-seq from the decomposition declaration, and a declarator
&optvi , where&is present if and only if it is present in the decomposition declaration. If the expression get0 is well-formed, the variable is initialized with the expression geti-1, otherwise it is initialized with the expression e.mi , where mi designates the i-th non-static data member ofE. The variable is copy-initialized or direct-initialized as indicated by the form of the brace-or-equal-initializer (8.5 [dcl.init]). [ Note: The type of vi is deduced from its initializer as described in the remainder of this section. -- end note ] [ Example:struct S { int x; volatile double y; }; const S f(); auto { x, y } = f();The type of x is "int", the type of y is "double". -- end example ]