... The type of the expression is the type of the identifier. The result is the entity denoted by the identifier. The result is the entity denoted by the identifier. The result is an lvalue if the entity is a function, variable, or data member and a prvalue otherwise. The result is a bit-field if the identifier designates a bit-field (7.1.6.4 [dcl.spec.auto]).Change in 5.2.5 [expr.ref] paragraph 3:
Abbreviating postfix-expression.id-expressionx as E1.E2, E1 is called the object expression. IfIn section 6.5 [stmt.iter] paragraph 1, change the grammar to allow a decomposition declaration:E2
is a bit-field,E1.E2
is a bit-field. ...
In section 7 [dcl.dcl] paragraph 1, change the grammar to allow a decomposition declaration:for-range-declaration: attribute-specifier-seqopt decl-specifier-seq declarator attribute-specifier-seqopt decl-specifier-seq ref-qualifieropt [ identifier-list ]
Add a new paragraph after 7 [dcl.dcl] paragraph 8:simple-declaration: decl-specifier-seq init-declarator-listopt ; attribute-specifier-seq decl-specifier-seq init-declarator-list ; attribute-specifier-seqopt decl-specifier-seq ref-qualifieropt [ identifier-list ] brace-or-equal-initializer ;
A simple-declaration with an identifier-list is
called a decomposition declaration. The
decl-specifier-seq shall contain only the
type-specifier 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 }", where the
assignment-expression is of array or non-union class
type.
Change in 7.1.6.2 [dcl.type.simple] paragraph 4:
For an expression e, the type denoted byAdd after 7.1.6.4 [dcl.spec.auto] paragraph 8:decltype(e)
is defined as follows:
- if e is an unparenthesized id-expression naming an lvalue or reference introduced from the identifier-list of a decomposition declaration,
decltype(e)
is the referenced type as given in the specification of the decomposition declaration (7.1.6.4 [dcl.spec.auto]);- otherwise, if e is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;
- otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;
- otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
- otherwise, decltype(e) is the type of e.
A decomposition declaration introduces the identifiers of the identifier-list as names in the order of appearance, where vi denotes the i-th identifier, with numbering starting at 1. Let cv denote the cv-qualifiers in the decl-specifier-seq. First, a variable with a unique name e is introduced. If the assignment-expression in the brace-or-equal-initializer has array type A and no ref-qualifier is present,e
has type cvA
and is copy-initialized or direct-initialized from the assignment-expression as specified by the form of the brace-or-equal-initializer. Otherwise,e
is defined as-if byattribute-specifier-seqopt decl-specifier-seq ref-qualifieropt e brace-or-equal-initializer ;where the parts of the declaration other than the declarator-id are taken from the corresponding decomposition declaration. The type of the expressione
is calledE
. [ Note:E
is never a reference type (Clause 5 [expr]). -- end note ]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 ofE
. Each vi is the name of an lvalue that refers to the element i-1 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 ]Otherwise, if the expression
std::tuple_size<E>::value
is a well-formed integral constant expression, the number of elements in the identifier-list shall be equal to the value of that expression. The unqualified-idget
is looked up in the scope ofE
by class member access lookup (3.4.5 [basic.lookup.classref]), and if that finds at least one declaration, the initializer ise.get<i-1>()
. Otherwise, the initializer isget<i-1>(e)
, whereget
is 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 ] In either case,e
is an lvalue if the type of the entitye
is an lvalue reference and an xvalue otherwise. Given the type Ti designated bystd::tuple_element<i-1,E>::type
, each vi is a variable of type "reference to Ti" initialized with the initializer, where the reference is an lvalue reference if the initializer is an lvalue and an rvalue reference otherwise; the referenced type is Ti.Otherwise, all of
E
's non-static data members and bit-fields shall be public direct members ofE
or of the same unambiguous public base class ofE
,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 ofE
. The i-th non-static data member of E in declaration order is designated by mi. Each vi is the name of an lvalue that refers to the member mi ofe
and whose type is cv Ti, where Ti is the declared type of that member; the referenced type is cv Ti. The lvalue is a bit-field if that member is a bit-field. [ Example:struct S { int x; volatile double y; }; S f(); const auto [ x, y ] = f();The type of the expressionx
is "const int", the type of the expressiony
is "const volatile double". -- end example ]