<html>
<head>
<title>P0217R1: Wording for structured bindings</title>

<style type="text/css">
  ins { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  .new { text-decoration:none; font-weight:bold; background-color:#D0FFD0 }
  .rule { background-color:#FFFF40 }
  .ex { background-color: #D0FFF0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }  
  strong { font-weight: inherit; color: #2020ff }
</style>
</head>

<body>
P0217R1<br/>
Jens Maurer &lt;Jens.Maurer@gmx.net><br/>
Audience: Evolution and Core Working Groups<br/>
2016-03-20<br/>

<h1>P0217R1: Proposed wording for structured bindings</h1>

<h2>Introduction</h2>

This paper presents the proposed wording to implement structured
bindings as described by Herb Sutter, Bjarne Stroustrup, and Gabriel
dos Reis in P0144R2.  That paper incorporates feedback from the EWG
session in Jacksonville as follows:

<ul>
<li>change to [] syntax</li>

<li>introduced variables are, in all cases, references to the value of
the initializer</li>

<li>the cv-qualifiers and ref-qualifier of the decomposition
declaration are applied to the reference introduced for the
initializer, not for the individual member aliases</li>

<li>support bit-fields</li>

<li>use tuple_size and tuple_element</li>

</ul>

In this paper, changes relative to the predecessor P0217R0 are
highlighted with <strong>blue text</strong>.  The specifications for a
decomposition declaration in section 7.1.6.4 have been rewritten
almost entirely and are not so marked.

<h2>Wording</h2>

<strong>Change in 5.1.1 [expr.prim] paragraph 8:</strong>

<blockquote>
... 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. <ins>The result is a bit-field if the identifier designates
a bit-field (7.1.6.4 [dcl.spec.auto]).</ins>

</blockquote>

<strong>Change in 5.2.5 [expr.ref] paragraph 3:</strong>

<blockquote>

Abbreviating <em>postfix-expression</em>.<em>id-expression</em>x as
E1.E2, E1 is called the object expression. <ins>If <code>E2</code> is
a bit-field, <code>E1.E2</code> is a bit-field.</ins> ...

</blockquote>

In section 6.5 [stmt.iter] paragraph 1, change the grammar to allow a
decomposition declaration:

<blockquote>
<pre>
<em>for-range-declaration:
      attribute-specifier-seq<sub>opt</sub> decl-specifier-seq declarator</em>
      <ins><em>attribute-specifier-seq</em><sub>opt</sub> <em>decl-specifier-seq</em> <strong><em>ref-qualifier</em></strong><sub>opt</sub> <strong>[</strong> <em>identifier-list</em> <strong>]</strong></ins>
</pre>
</blockquote>

In section 7 [dcl.dcl] paragraph 1, change the grammar to allow a
decomposition declaration:

<blockquote>
<pre>
<em>simple-declaration:
      decl-specifier-seq init-declarator-list<sub>opt</sub></em> ;
      <em>attribute-specifier-seq decl-specifier-seq init-declarator-list</em> ;
      <ins><em>attribute-specifier-seq</em><sub>opt</sub> <em>decl-specifier-seq</em> <strong><em>ref-qualifier</em></strong><sub>opt</sub> <strong>[</strong> <em>identifier-list</em> <strong>]</strong> <em>brace-or-equal-initializer</em> ;</ins>
</pre>
</blockquote>

Add a new paragraph after 7 [dcl.dcl] paragraph 8:

<blockquote class="new">
A <em>simple-declaration</em> with an <em>identifier-list</em> is
called a <em>decomposition declaration</em>. The
<em>decl-specifier-seq</em> shall contain only the
<em>type-specifier</em> <code>auto</code> (7.1.6.4 [dcl.spec.auto])
and <em>cv-qualifier</em>s.  The <em>brace-or-equal-initializer</em>
shall be of the form "= <em>assignment-expression</em>" or of the form
"{ <em>assignment-expression</em> }"<strong>, where the
<em>assignment-expression</em> is of array or non-union class
type</strong>.

</blockquote>

<strong>Change in 7.1.6.2 [dcl.type.simple] paragraph 4:</strong>

<blockquote>
For an expression e, the type denoted by <code>decltype(e)</code> is
defined as follows:

<ul>

<li><ins>if e is an unparenthesized <em>id-expression</em> naming an
lvalue or reference introduced from the <em>identifier-list</em> of a
decomposition declaration, <code>decltype(e)</code> is the referenced
type as given in the specification of the decomposition declaration
(7.1.6.4 [dcl.spec.auto]);</ins></li>
  
<li><ins>otherwise,</ins> 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;</li>

<li>otherwise, if e is an xvalue, decltype(e) is T&&, where T is the
type of e;</li>

<li>otherwise, if e is an lvalue, decltype(e) is T&, where T is the
type of e;</li>
  
<li>otherwise, decltype(e) is the type of e.</li>
</ul>

</blockquote>


<strong>Add after 7.1.6.4 [dcl.spec.auto] paragraph 8:</strong>

<blockquote class="new">
A decomposition declaration introduces the <em>identifier</em>s of the
<em>identifier-list</em> as names in the order of appearance, where
<em>v<sub>i</sub></em> denotes the <em>i</em>-th identifier, with
numbering starting at 1.  Let <em>cv</em> denote the
<em>cv-qualifier</em>s in the <em>decl-specifier-seq</em>. First, a
variable with a unique name <em>e</em> is introduced.  If the
<em>assignment-expression</em> in the
<em>brace-or-equal-initializer</em> has array type A and no
<em>ref-qualifier</em> is present, <code>e</code> has type <em>cv</em>
<code>A</code> and is copy-initialized or direct-initialized from the
<em>assignment-expression</em> as specified by the form of the
<em>brace-or-equal-initializer</em>.

Otherwise, <code>e</code> is defined as-if by

<pre>
  <em>attribute-specifier-seq</em><sub>opt</sub> <em>decl-specifier-seq</em> <em>ref-qualifier</em><sub>opt</sub> <em>e</em> <em>brace-or-equal-initializer</em> ;
</pre>

where the parts of the declaration other than the
<em>declarator-id</em> are taken from the corresponding decomposition
declaration.  The type of the expression <code>e</code> is called
<code>E</code>. [ Note: <code>E</code> is never a reference type
(Clause 5 [expr]). -- end note ]

<p>

If <code>E</code> is an array type with element type T, the number of
elements in the <em>identifier-list</em> shall be equal to the number
of elements of <code>E</code>.  Each <em>v<sub>i</sub></em> is the
name of an lvalue that refers to the element <em>i</em>-1 of the array
and whose type is T; the referenced type is T.  [ Note: The top-level
cv-qualifiers of T are <em>cv</em>. -- end note ]</li>

<p>
Otherwise, if the expression <code>std::tuple_size&lt;E>::value</code>
is a well-formed integral constant expression, the number of elements
in the <em>identifier-list</em> shall be equal to the value of that
expression.  The <em>unqualified-id</em> <code>get</code> is looked up
in the scope of <code>E</code> by class member access lookup (3.4.5
[basic.lookup.classref]), and if that finds at least one declaration,
the initializer is <code><em>e</em>.get&lt;<em>i</em>-1>()</code>.
Otherwise, the initializer is
<code>get&lt;<em>i</em>-1>(<em>e</em>)</code>, where <code>get</code>
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,
<code>e</code> is an lvalue if the type of the entity <code>e</code>
is an lvalue reference and an xvalue otherwise.  Given the type
T<sub>i</sub> designated by
<code>std::tuple_element&lt;<em>i</em>-1,E>::type</code>, each
<em>v<sub>i</sub></em> is a variable of type "reference to
T<sub>i</sub>" 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 T<sub>i</sub>.

</li>

<p>
Otherwise, all of <code>E</code>'s non-static data members and
bit-fields shall be public direct members of <code>E</code> or of the
same unambiguous public base class of <code>E</code>, <code>E</code>
shall not have an anonymous union member, and the number of elements
in the <em>identifier-list</em> shall be equal to the number of
non-static data members of <code>E</code>.  The <em>i</em>-th
non-static data member of E in declaration order is designated by
<em>m<sub>i</sub></em>.  Each <em>v<sub>i</sub></em> is the name of an
lvalue that refers to the member <em>m<sub>i</sub></em> of
<code>e</code> and whose type is <em>cv</em> T<sub>i</sub>, where
T<sub>i</sub> is the declared type of that member; the referenced type
is <em>cv</em> T<sub>i</sub>.  The lvalue is a bit-field if that
member is a bit-field.

</li>

</ul>

[ Example:
<pre>
struct S { int x; volatile double y; };
S f();
const auto [ x, y ] = f();
</pre>

The type of the expression <code>x</code> is "const int", the type of
the expression <code>y</code> is "const volatile double". -- end
example ]

</blockquote>

</body>
</html>
