<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
  <title>init-list wording</title>
</head>
<body>
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8">
<h1>Initializer List proposed wording</h1>
Jason Merrill, Daveed Vandevoorde
<br>2008-06-12
<br>Document number N2672=08-0182
<br>Revision 22

<h2>Introduction</h2>
This paper is an update of the proposed wording for the initializer list
proposal in N2640=08-0150 from the pre-Sophia Antipolis mailing.  The
wording is strongly derived from the wording in N2531=08-0041 by J. Stephen
Adamczyk, Gabriel Dos Reis, and Bjarne Stroustrup.

<p>The changes to clauses 18 and 20 are from N2531=08-0041; the LWG felt that
  they belong with the core wording.</p>

<h2>Proposed Wording</h2>

<p>In 8.5 [dcl.init],
change
</p>
<pre>
  <i>initializer</i>:
    = <i>initializer-clause</i>
    ( <i>expression-list</i> )
    <i><ins>braced-init-list</ins></i>

  <i>initializer-clause</i>:
    <i>assignment-expression</i>
    <del>{ <i>initializer-list</i> ,<sub><i>opt</i></sub>}</del>
    <del>{ }</del>
    <i><ins>braced-init-list</ins></i>

  <i>initializer-list:</i>
    <i>initializer-clause ...<sub>opt</sub></i>
    <i>initializer-list , initializer-clause ...<sub>opt</sub></i>

  <ins><i>braced-init-list:</i></ins>
    <ins>{ <i>initializer-list</i> ,<sub><i>opt</i></sub> }</ins>
    <ins>{ }</ins>
</pre>

<p>In 5.2 [expr.post], change</p>
<pre>
  <i>postfix-expression</i>:
    ...
    <i>postfix-expression</i> [ <i>expression </i>]
    <ins><i>postfix-expression</i> [ <i>braced-init-list </i>]</ins>
    <i>postfix-expression</i> ( <i>expression-list<sub>opt</sub></i> )
    <i>simple-type-specifier</i> ( <i>expression-list<sub>opt</sub></i> )
    <i>typename-specifier</i> ( <i>expression-list<sub>opt</sub></i> )
    <ins><i>simple-type-specifier</i> <i>braced-init-list</i></ins>
    <ins><i>typename-specifier</i> <i>braced-init-list</i></ins>
    ...

  <i>expression-list:</i>
    <del><i>assignment-expression ...<sub>opt</sub></i></del>
    <del><i>expression-list , assignment-expression ...<sub>opt</sub></i></del>
    <i><ins>initializer-list</ins></i>
</pre>

<p>In 5.3.4 [expr.new], change</p>

<pre>
  <i>new-initializer</i>:
    ( <i>expression-list<sub>opt</sub></i> )
    <i><ins>braced-init-list</ins></i>
</pre>

<p>In 5.17 [expr.ass], change</p>
<pre>
  <i>assignment-expression</i>:
    <i>conditional-expression</i>
    <del><i>logical-or-expression assignment-operator assignment-expression </i></del>
    <i><ins>logical-or-expression assignment-operator initializer-clause </ins></i>
    <i>throw-expression</i>
</pre>

<p>In 6.4 [stmt.select], change</p>
<pre>
  <i>condition</i>:
    <i>expression</i>
    <i>type-specifier-seq declarator</i> <tt>=</tt> <i><del>assignment-expression</del><ins>initializer-clause</ins></i>
    <ins><i>type-specifier-seq declarator braced-init-list</i></ins>
</pre>

<p>In 6.6 [stmt.jump], change</p>
<pre>
  <i>jump-statement</i>:
    ...
    return <i>expression<sub>opt</sub></i> ;
    <ins>return <i>braced-init-list</i> ;</ins>
    ...
</pre>

<p>In 12.6.2 [class.base.init], change</p>
<pre>
  <i>mem-initializer</i>:
    <i>mem-initializer-id</i> ( <i>expression-list<sub>opt</sub></i> ) 
    <ins><i>mem-initializer-id</i> <i>braced-init-list</i></ins>
</pre>

<p>In 8.5 [dcl.init], change paragraphs 12-15:</p>
<blockquote>
The initialization that occurs <ins>in the form
<pre>
  T x = a;
</pre>
as well as</ins> in argument passing, function return,
throwing an exception (15.1), handling an exception (15.3), and
<del>brace-enclosed initializer lists</del><ins>aggregate member
  initialization</ins> (8.5.1) is called <i>copy-initialization</i><ins>.</ins>
<del>and is equivalent to the form
<pre>
  T x = a;
</pre></del>
<p>The initialization that occurs <ins>in the forms
<pre>
  T x(a);
  T x{a};
</pre>
as well as</ins> in <code>new</code> expressions (5.3.4), <code>static_cast</code>
expressions (5.2.9), functional notation type conversions (5.2.3), and
  base and member initializers (12.6.2) is called <i>direct-initialization</i><ins>.</ins>
<del>and is equivalent to the form
<pre>
  T x(a);
</pre></del>
</p>
</blockquote>

<del>
<blockquote>
<p>If T is a
scalar type, then a declaration of the form</p>
<pre>
  T x = { a };
</pre>
<p>is equivalent to</p>
<pre>
  T x = a;
</pre>
</blockquote>
</del>

<blockquote>
<p>The semantics of
initializers are as follows. The <i>destination type</i> is the type
of the object or reference being initialized and the <i>source type</i>
is the type of the initializer expression. The source type is not
  defined when the initializer is <del>brace-enclosed</del><ins>a <i>braced-init-list</i></ins> or
when it is a parenthesized list of expressions.</p>
<ul>
  <li>
    If the destination type
is a reference type, see <font color="blue">8.5.3</font>.
  </li>
  <li>
    If the destination type is an array of
characters, an array of <tt>char16_t</tt>, an array of <tt>char32_t</tt>, or an array of <tt>wchar_t</tt>, and the initializer is a string
literal, see <font color="blue">8.5.2</font>.
  </li>
  <li>
    <ins>If the initializer is a <i>braced-init-list</i>, the object is 
list-initialized ([dcl.init.list]).</ins>
  </li>
  <li>
    <ins>If the initializer is <tt>()</tt>, the object is
    value-initialized.</ins>
  </li>
  <li>
    Otherwise, if the
destination type is an array, <del>see <font
 color="blue">8.5.1</del></font> <ins>the program is
ill-formed</ins>.
  </li>
  <li>
    If the destination type is a (possibly cv-qualified) class type:
    <ul>
      <li>
        <del>If the class is an aggregate
(<font color="blue">8.5.1</font>), and the initializer is a
brace-enclosed list, see <font color="blue">8.5.1</font>.</del>
      </li>
      <li>
        If the initialization is direct-initialization, ...
      </li>
    </ul>
  </li>
</ul>
</blockquote>


<p>In 8.5.1 [decl.init.aggr] paragraph 2, change</p>
<blockquote>
<del>When an aggregate is initialized the <i>initializer</i> can contain
an <i>initializer-clause</i> consisting of a brace-enclosed ,
comma-separated list of <i>initializer-clause</i></del><ins>When,
as specified in [dcl.init.list], an aggregate is initialized by
an initializer list, the elements of the initializer list are taken
as initializers</ins> for the members of the aggregate, <del>written</del> in
increasing subscript or member order. <del>If the aggregate
contains subaggregates, this rule applies recursively to the members
of the subaggregate.</del> <ins>Each member is copy-initialized from the
corresponding <i>initializer-clause.</i> If the
<i>initializer-clause</i> is an expression and a narrowing conversion
([dcl.init.list]) is required to convert the expression, the program
is ill-formed. [<i>Note:</i> If an <i>initializer-clause</i> is
itself an initializer list, the member is list-initialized, which will 
result in a recursive application of the rules in this section 
if the member is an aggregate. --<i>end note</i>]</ins> [ <i>Example:</i> ...
</blockquote>

<p>In 8.5.1 paragraph 11:</p>
<blockquote>
<ins>In a declaration of the form
<pre>
  T x = { a };
</pre>
b</ins><del>B</del>races can be elided in an <i>initializer-list</i> as follows.
<ins>[Footnote: Braces cannot be elided in other uses of list-initialization.]</ins>
If the <i>initializer-list</i> begins with a left brace, ....
</blockquote>

<p>In 8.5 [dcl.init], add a new section as
8.5.4 [dcl.init.list]:</p>

<blockquote>
<p>8.5.4
<b>List-initialization</b> [dcl.init.list]</p>
<p><i>List-initialization</i> is initialization of an object or reference
from a <i>braced-init-list</i>. Such an
initializer is called an <i>initializer list</i>, and the comma-separated
  <i>initializer-clause</i>s of the list are called
the <i>elements</i> of the initializer list. An initializer list may be
empty.
List-initialization can occur in direct-initialization or
copy-initialization contexts; list-initialization in a
direct-initialization context is called <i>direct-list-initialization</i>
and list-initialization in a copy-initialization context is
called <i>copy-list-initialization</i>.
[ <i>Note</i>: List-initialization can be used</p>
<ul>
  <li>
    as the initializer in a variable definition (8.5 [dcl.init])
  </li>
  <li>
    as the initializer in a new expression (5.3.4 [expr.new])
  </li>
  <li>
    in a return statement (6.6.3 [stmt.return])  
  </li>
  <li>as a function argument (5.2.2 [expr.call])</li>
  <li>
    as a subscript (5.2.1 [expr.sub])
  </li>
  <li>
    as an argument to a constructor invocation (8.5 [dcl.init], 5.2.3 [expr.type.conv])
  </li>
  <li>
    as a base-or-member initializer (12.6.2 [class.base.init])
  </li>
  <li>on the right-hand side of an assignment (5.17)</li>
</ul>
<p> [ <i>Example:</i></p>
<pre>
  int a = {1};
  std::complex&lt;double&gt; z{1,2};
  new std::vector&lt;std::string&gt;{"once", "upon", "a", "time"}; // 4 string elements
  f( {"Nicholas","Annemarie"} ); // pass list of two elements
  return { "Norah" }; // return list of one element
  int* e {}; // initialization to zero / null pointer
  x = double{1}; // explicitly construct a double 
  std::map&lt;std::string,int&gt; anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} };
</pre>
<p>--- <i>end example</i>
]--- <i>end note</i> ]</p>
<p>A constructor is an <i>initializer-list constructor</i> if its first 
parameter is of type <tt>std::initializer_list&lt;E&gt;</tt> or reference to 
possibly cv-qualified <tt>std::initializer_list&lt;E&gt;</tt> for some type
 <tt>E</tt>, and either there are no other parameters or else all other
 parameters have default arguments (<font color="blue">8.3.6</font>).
[<i>Note:</i> Initializer-list constructors are favored over other
constructors in list-initialization ([over.match.list]).] The
template <tt>std::initializer_list</tt> is not predefined; if the
header <tt>&lt;initializer_list&gt;</tt> is not included prior to a use
of <tt>std::initializer_list</tt>--even an implicit use in which the type
is not named ([dcl.spec.auto])--the program is ill-formed.</p>

<p>List-initialization of an object or reference of type T is defined as
follows.</p>
<ol>
  <li>
    <p>If T is an aggregate, aggregate initialization is performed
(8.5.1 [dcl.init.aggr]). [<i>Example:</i></p>
<pre>
  double ad[] = { 1, 2.0 }; // ok
  int ai[] = { 1, 2.0 }; // error: narrowing
</pre>
<p>--- <i>end example</i>]</p>
  </li>
  <li>Otherwise, if T is a specialization of <tt>std::initializer_list&lt;E&gt;</tt>,
an <tt>initializer_list</tt> object is constructed as described below
and used to initialize the object according to the rules for
initialization of an object from a class of the same type (8.5).</li>
  <li>
    <p>Otherwise, if T is a class type, constructors are considered.  If T
has an initializer-list constructor, the argument list consists of the initializer
list as a single argument; otherwise, the argument list
consists of the elements of the initializer list.  The applicable
constructors are enumerated ([over.match.list]) and the best one is chosen through
overload resolution (13.3).  If a narrowing conversion (see below) is
required to convert any of the arguments, the program is ill-formed.</p>
<p>[ <i>Example:</i></p>
<pre>
  struct S {
    S(std::initializer_list&lt;double&gt;); // #1
    S(std::initializer_list&lt;int&gt;); // #2
    // ...
  };
  S s1 = { 1.0, 2.0, 3.0 }; // invoke #1
  S s2 = { 1, 2, 3 }; // invoke #2
</pre>
<p>--- <i>end example</i>]</p>
<p>[ <i>Example:</i></p>
<pre>
  struct Map {
    Map(std::initializer_list&lt;std::pair&lt;std::string,int&gt;&gt;);
  };
  Map ship = {{"Sophie",14}, {"Surprise",28}}; 
</pre>
<p>--- <i>end example</i>]</p>
<p>[ <i>Example:</i></p>
<pre>
  struct S {
    // no initializer-list constructors
    S(int, double, double); // #2
    S(); // #3
    // ...
  };
  S s1 = { 1, 2, 3.0 };  // ok: invoke #2
  S s2 { 1.0, 2, 3 }; // error: narrowing
  S s3 { }; // ok: invoke #3

  struct S2 {
    int m1;
    double m2,m3;
  };
  S2 s21 = { 1, 2, 3.0 }; // ok
  S2 s22 { 1.0, 2, 3 }; // error: narrowing
  S2 s23 {}; // ok: default to 0,0,0
</pre>
<p>--- <i>end example</i>]</p>
  </li>
  <li>
    <p>Otherwise, if T is a reference type, an rvalue temporary of the
type referenced by T is list-initialized, and the reference is bound to
that temporary. [ <i>Note:</i> As usual, the binding will fail and the program is
ill-formed if the reference type is an lvalue reference to a non-const
type. ]</p>
<p>
[ <i>Example:</i></p>
<pre>
  struct S {
    S(std::initializer_list&lt;double&gt;); // #1
    S(const std::string&amp;); // #2
    // ...
  };
  const S&amp; r1 = { 1, 2, 3.0 }; // ok: invoke #1
  const S&amp; r2 { "Spinach" }; // ok: invoke #2
  S&amp; r3 = { 1, 2, 3 }; // error: initializer is not an lvalue
</pre>
    <p>--- <i>end example</i>]</p>
  </li>
  <li>
    <p>Otherwise (i.e., if T is
not an aggregate, class type, or reference), if the initializer list has
a single element, the object is initialized from that element; if a narrowing
conversion (see below) is required to convert the element to T, the
program is ill-formed. [ <i>Example:</i></p>
<pre>
  int x1 {2}; // ok
  int x2 {2.0}; // error: narrowing
</pre>
<p>
--- <i>end example</i>]</p>
  </li>
  <li>
    <p>Otherwise, if the initializer list
has no elements, the object is value-initialized; [<i> Example</i></p>
<pre>
  int** pp {}; // initialized to null pointer
</pre>
    <p><i>--- end example</i>]</p>
  </li>
  <li>
    <p>Otherwise, the program is ill-formed.</p>
  </li>
</ol>

<p>[ <i>Example:</i></p>
<pre>
  struct A { int i; int j; };
  A a1 { 1, 2 }; // aggregate initialization 
  A a2 { 1.2 }; // error: narrowing
  struct B {
    B(std::initializer_list&lt;int&gt;);
  };
  B b1 { 1, 2 }; // creates initializer_list&lt;int&gt; and calls constructor
  B b2 { 1, 2.0 }; // error: narrowing
  struct C {
    C(int i, double j);
  };
  C c1 = { 1, 2.2 }; // calls constructor with arguments (1, 2.2) 
  C c2 = { 1.1, 2 }; // error: narrowing

  int j { 1 }; // initialize to 1
  int k {}; // initialize to 0
</pre>
<p>--- <i>end example</i>]</p>
<p>When an initializer list is implicitly converted to a
<tt>std::initializer_list&lt;E&gt;</tt>,
the object passed is constructed as if the implementation
allocated an array of <b>N</b> elements of type <b>E</b>, where <b>N</b>
is the number of elements in the initializer list. Each element of
that array is initialized with the corresponding element of the
initializer list converted to E, and the <tt>std::initializer_list&lt;E&gt;</tt>
object is constructed to refer to that array. If a narrowing
conversion is required to convert the element to E, the
program is ill-formed. [ <i>Example:</i></p>
<pre>
  struct X {
    X(std::initializer_list&lt;double&gt; v);
  };
  X x{ 1,2,3 };
</pre>
<p>The initialization will be implemented in a way roughly equivalent to this:</p>
<pre>
  double __a[3] = {double{1}, double{2}, double{3}};
  X x(std::initializer_list&lt;double&gt;(__a, __a+3));
</pre>
<p>assuming that the implementation can construct an <tt>initializer_list</tt>
with a pair of pointers. --- <i>end example</i>]</p>
<p>The lifetime of the array is the same as that of the <tt>initializer_list</tt>
object. [<i>Example:</i></p>
<pre>
  typedef std::complex&lt;double&gt; cmplx;
  std::vector&lt;cmplx&gt; v1 = { 1, 2, 3 };

  void f()
  {
    std::vector&lt;cmplx&gt; v2{ 1, 2, 3 };
    std::initializer_list&lt;int&gt; i3 = { 1, 2, 3 };
  }
</pre>
<p>For
  <tt>v1</tt> and <tt>v2</tt>, the <tt>initializer_list</tt> object and array created for <tt>{ 1,
    2, 3 }</tt> have full-expression lifetime. For <tt>i3</tt>, the
  <tt>initializer_list</tt> object and array have automatic lifetime. --- <i>end
    example</i> ] [ <i>Note</i>: The implementation is free to allocate the array in read-only memory if an explicit array with the same initializer could be so allocated.  --- <i>end note</i>]</p>
<p>A <i>narrowing conversion</i> is an implicit conversion</p>
<ul>
  <li>
    <p>from a floating-point type to an integer type, or</p>
  </li>
  <li>
    <p>from <tt>long double</tt> to <tt>double</tt>
or <tt>float</tt>, or from <tt>double</tt> to <tt>float</tt>, except where
the source is a constant expression and the actual value after conversion
will fit into the target type and will produce the original value when
converted back to the original type, or</p>
  </li>
  <li>
    <p>from an integer type or unscoped enumeration type to a
floating-point type, except where the source is a constant expression and
the actual value after conversion will fit into the target type and will
produce the original value when converted back to the original type, or</p>
  </li>
  <li>
    <p>from an integer type or unscoped enumeration type to an integer type
that cannot represent all the values of the original type, except where the
source is a constant expression and the actual value after conversion will
fit into the target type and will produce the original value when converted
back to the original type.  </p>
  </li>
</ul>
<p>[<i>Note:</i> As indicated above, such conversions are not allowed at
the top level in list-initializations. [ <i>Example:</i></p>
<pre>
  int x = 999; //  x is not a constant expression
  const int y = 999;
  const int z = 99;
  char c1 = x; // ok, though it might narrow (in this case, it does narrow)
  char c2{x}; // error, might narrow
  char c3{y}; // error: narrows
  char c4{z}; // ok, no narrowing needed
  unsigned char uc1 = {5}; // ok: no narrowing needed
  unsigned char uc2 = {-1}; // error: narrows
  unsigned int ui1 = {-1}; // error: narrows
  signed int si1 = { (unsigned int)-1 }; // error: narrows
  int ii = {2.0}; // error: narrows
  float f1 { x }; // error: narrows
  float f2 { 7 }; // ok: 7 can be exactly represented as a float
  int f(int);
  int a[] = { 2, f(2), f(2.0) }; // ok: the double-to-int conversion is not at the top level
</pre>
<p>--- <i>end example</i>] ] </p>
</blockquote>


<p>In 5.2.1 [expr.sub], add
as a new paragraph 2:</p>
<blockquote>
<p>A <i>braced-init-list</i> may appear as a subscript for a user-defined
<tt>operator[]</tt>. In that case, the initializer list is treated as the
initializer for the subscript argument of the <tt>operator[]</tt>. An
initializer list shall not be used with the built-in subscript
operator. [ <i>Example:</i></p>
<pre>
  struct X {
    Z operator[](std::initializer_list&lt;int&gt;);
  };
  X x;
  x[{1,2,3}] = 7; // ok: meaning x.operator[]({1,2,3})
  int a[10];
  a[{1,2,3}] = 7; // error: built-in subscript operator
</pre>
<p>--- <i>end example</i>]</p>
</blockquote>

<p>In 5.2.3 [expr.type.conv], change:</p>
<blockquote>
<p>A <i>simple-type-specifier</i>
(<font color="blue">7.1.6.2</font>) <ins>or <i>typename-specifier</i>
(<font color="blue">14.6</font>)</ins> followed by a
parenthesized <i>expression-list</i> constructs a value of the specified
type given the expression list. If the expression list is a single
expression, the type conversion expression is equivalent (in definedness,
and if defined in meaning) to the corresponding cast expression
(<font color="blue">5.4</font>). If the
  <del><i>simple-type-specifier</i> specifies</del><ins>type specified
is</ins> a class type, the class type shall be complete. If the expression
list specifies more than a single value, the type shall be a class with a
suitably declared constructor
(<font color="blue">8.5</font>, <font color="blue">12.1</font>), and the
expression <tt>T(x1, x2, ...)</tt> is equivalent in effect to the
declaration <tt>T t(x1, x2, ...);</tt> for some invented temporary
variable <tt>t</tt>, with the result being the value of <tt>t</tt> as an
rvalue.</p>

<p>The expression <tt>T()</tt>, where <tt>T</tt> is
a <i>simple-type-specifier</i> <del>(<font color="blue">7.1.6.2</font>)</del> <ins>or
typename-specifier</ins> for a non-array complete object type or the
(possibly cv-qualified) void type, creates an rvalue of the specified type,
which is value-initialized (<font color="blue">8.5</font>; no
initialization is done for the <tt>void()</tt> case). [ <i>Note:</i>
if <tt>T</tt> is a non-class type that is cv-qualified, the cv-qualifiers
are ignored when determining the type of the resulting rvalue
(<font color="blue">3.10</font>). --- <i>end note</i> ]</p>

<ins><p>Similarly, a <i>simple-type-specifier</i>
or <i>typename-specifier</i> followed by a <i>braced-init-list</i> creates a
temporary object of the specified type direct-list-initialized
(<font color="blue">[dcl.init.list]</font>) with the specified <i>braced-init-list</i>, and
its value is that temporary object as an rvalue.</p></ins>
</blockquote>

<p>In 5.3.4 [expr.new] paragraph 16, change part of the bullet list:</p>
<blockquote>
<ul>
  <li>
    ...
  </li>
  <li>
    <del>If the <i>new-initializer</i> is of the form <tt>()</tt>,
    the item is value-initialized
    (<font color="blue">8.5</font>);</del>
  </li>
  <li>
    <del>If the <i>new-initializer</i> is of the form <tt>(</tt><i>expression-list</i><tt>)</tt> and T is a class type, the appropriate
constructor is called, using <i>expression-list</i> as the arguments (<font
 color="blue">8.5</font>);</del>
  </li>
  <li>
    <del>If the <i>new-initializer</i> is of the
      form <tt>(<i>expression-list</i></tt> <tt>)</tt> and T is an
      arithmetic, enumeration, pointer, or 
pointer-to-member type and <i>expression-list</i> comprises exactly one expression, then
the object is initialized to the (possibly converted) value of the
      expression (<font color="blue">8.5</font>);</del>
  </li>
  <li>
    <del>Otherwise the new-expression is ill-formed.</del>
  </li>
  <li>
    <ins>Otherwise, the <i>new-initializer</i> is interpreted according to
the initialization rules of 8.5 [dcl.init] for direct-initialization.</ins>
  </li>
</ul>
</blockquote>
<p>In 5.17 [expr.ass], add as a new final paragraph:</p>
<blockquote>
<p>A <i>braced-init-list</i> may appear on the right-hand side of</p>
<ul>
  <li>
    <p>an assignment to a scalar, in which case the initializer list must
have at most a single element. The meaning of <tt>x={v}</tt>, where <b>T</b>
is the scalar type of the expression <tt>x</tt>, is that
of <tt>x=T(v)</tt> except that no narrowing conversion ([dcl.init.list]) is allowed. The
meaning of <tt>x={}</tt> is <tt>x=T()</tt>.</p>
  </li>
  <li>
    <p>an assignment defined by a user-defined assignment operator, in
which case the initializer list is passed as the argument to the operator
function.</p>
  </li>
</ul>
<p>[<i>Example:</i> </p>
<pre>
  complex&lt;double&gt; z;
  z = { 1,2 }; // meaning z.operator=({1,2})
  z += { 1, 2 }; // meaning z.operator+=({1,2})
  a = b = { 1 }; // meaning a=b=1;
  a = { 1 } = b; // syntax error
</pre>
<p>--- <i>end example</i>]</p>
</blockquote>

<p>In 6.4 paragraph 2:</p>
<blockquote>
  ... If the <tt>auto</tt> <i>type-specifier</i> appears in
  the <i>type-specifier-seq</i>, the <i>type-specifier-seq</i> shall
  contain no other <i>type-specifiers</i> except <i>cv-qualifiers</i>, and
  the type of the identifier being declared is deduced from
  the <del><i>assignment-expression</i></del><ins>initializer</ins> as
  described in <font color="blue">7.1.6.4</font>.
</blockquote>


<p>In 6.6.3 [stmt.return] paragraph 2,
change</p>
<blockquote>
<p>A return statement without an expression can be used only in functions
that do not return a value, that is, a function with the return type void,
a constructor (<font color="blue">12.1</font>), or a destructor
(<font color="blue">12.4</font>). A return statement with an expression
of non-void type can be used only in functions returning a value; the value
of the expression is returned to the caller of the function. The expression
is implicitly converted to the return type of the function in which it
appears. A return statement can involve the construction and copy of a
temporary object (<font color="blue">12.2</font>).  [ <i>Note:</i> A
copy operation associated with a return statement may be elided or
considered as an rvalue for the purpose of overload resolution in selecting
a constructor (<font color="blue">12.8</font>).  -- <i>end note</i>
] <ins>A return statement with a <i>braced-init-list</i> initializes
the object or reference to be returned from the function by
copy-list-initialization ([dcl.init.list]) from the specified initializer
list. [ <i>Example:</i></p>
<pre>
  std::pair&lt;std::string,int&gt; f(const char* p, int x)
  {
    return {p,x};
  }
</pre>
<p>--- <i>end example</i>]</p></ins>
<p>Flowing off the end of a function is equivalent to a return with no
value; this results in undefined behavior in a value-returning
function.</p>
</blockquote>
<p>In 7.1.6.4 [dcl.spec.auto], paragraph 6, change</p>
<blockquote>
<p>Once the type of a <i>declarator-id</i> has been determined according to
<font color="blue">8.3</font>, the type of the declared variable
using the <i>declarator-id</i> is determined from the type of its
initializer using the rules for template argument deduction. Let T be
the type that has been determined for a variable identifier d. Obtain
P from T by replacing the occurrences of auto with <ins>either</ins> a new invented
type template parameter U <ins>or, if the initializer is a <i>braced-init-list</i> ([dcl.init.list]),
with <tt>std::initializer_list&lt;U&gt;</tt></ins>. <del>Let A be the type of the
  initializer expression for d.</del>
The type deduced for the variable d is then the deduced type determined
using the rules of template argument deduction from a function call
(<font color="blue">14.8.2.1</font>), where P is a function template
parameter type and <del>A</del><ins>the initializer for d</ins> is the 
corresponding argument <del>type</del>. If the deduction
fails, the declaration is ill-formed.
<ins>[ <i>Example:</i></p>
<pre>
  auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list&lt;int&gt;
  auto x2 = { 1, 2.0 }; // error: cannot deduce element type
</pre>
<p>--- <i>end example</i>]</p></ins>
</blockquote>

<p>In 12.2 [class.temporary], paragraph 3, change</p>
<blockquote>
<p>The second context is when a reference is bound to a temporary. The
temporary to which the reference is bound or the temporary that is the
complete object of a subobject to which the reference is bound persists for
the lifetime of the reference except as specified below.  A temporary bound
to a reference member in a constructor's ctor-initializer
(<font color="blue">12.6.2</font>) persists until the constructor
exits. A temporary bound to a reference parameter in a function call
(<font color="blue">5.2.2</font>) persists until the completion of the
full expression containing the call. A temporary bound to the returned
value in a function return statement (<font color="blue">6.6.3</font>)
persists until the function exits. <ins>A temporary bound to a reference in
a <i>new-initializer</i> (5.3.4 [expr.new]) persists until the completion
of the full-expression containing
    the <i>new-initializer</i> [<i>Example:</i></ins></p>
<ins>
<pre>
  struct S { int mi; const std::pair&lt;int,int&gt;&amp; mp; };
  S a { 1, {2,3} };
  S* p = new S{ 1, {2,3} }; // Creates dangling reference
</pre>
</ins>
<p><ins>--- <i>end example</i>]
[ <i>Note: </i>This may introduce a dangling reference,
and implementations are encouraged to issue a warning in such a case.
--- <i>end note</i>]</ins> The destruction of a temporary whose lifetime is
not extended by being bound to a reference is sequenced before the
destruction of every temporary which is constructed earlier in the same
full-expression. ...</p>
</blockquote>

<p>In 12.3.1 [class.conv.ctor] paragraph 1, change</p>
<blockquote>
<p>A constructor declared without the <i>function-specifier</i>
<tt>explicit</tt> <del>that can be called with a single parameter</del>
specifies a conversion from the <del>type of its first
parameter</del><ins>types of its parameters</ins> to the type of its
class. Such a constructor is called a <i>converting constructor</i>.</p>
</blockquote>

<p>In 12.6.1 [class.expl.init] paragraph 2, change</p>
<blockquote>
<p><del>When an
aggregate (whether class or array) contains members of class type and
is initialized by a brace-enclosed <i>initializer-list</i>
(<font color="blue">8.5.1</font>),
each such member is copy-initialized (see <font
 color="blue">8.5</font>)
by the corresponding <i>assignment-expression</i>.
If there are fewer <i>initializer</i>s in the <i>initializer-list</i>
than members of the aggregate, each member not explicitly initialized
shall be value-initialized (<font color="blue">8.5</font>).
[ Note: <font color="blue">8.5.1 </font>describes
how <i>assignment-expression</i>s
in an <i>initializer-list</i> are
paired with the aggregate members they initialize. --end note ]</del>
<ins>An object of class type can also be initialized by a
  <i>braced-init-list</i>. List-initialization semantics apply;
see 8.5 [dcl.init] and [dcl.init.list].</ins> [ Example: ...</p>
</blockquote>
<p>In 12.6.2 [class.base.init] paragraph 3, change</p>
<blockquote>
  <p>The <i>expression-list</i> <ins>or <i>braced-init-list</i></ins>
 in a <i>mem-initializer</i> is used
to initialize the base class or non-static data member subobject
denoted by the <i>mem-initializer-id</i> <ins>according to the
  initialization rules of 8.5 [dcl.init] for direct-initialization.</ins><del>
The semantics of a <i>mem-initializer</i>
are as follows:</del></p>
<ul>
  <li>
    <p><del>if the
expression-list of the <i>mem-initializer</i>
is omitted, the base class or member subobject is value-initialized
(see <font color="blue">8.5</font>);</del></p>
  </li>
  <li>
    <p><del>otherwise, the
subobject indicated by <i>mem-initializer-id</i>
is direct-initialized using <i>expression-list</i>
as the initializer (see <font color="blue">8.5</font>).</del></p>
  </li>
</ul>
</blockquote>
<p>In 13.3.1p6, change</p>
<blockquote>
  <p>Because <ins>other than in list-initialization</ins> only one user-defined
  conversion is allowed in an implicit conversion sequence, special rules
  apply when selecting the best user-defined conversion (13.3.3,
  13.3.3.1).</p>
</blockquote>

<p>Add a new section 13.3.1.7:</p>
<blockquote>
<p>13.3.1.7 <b>Initialization by list-initialization </b>[over.match.list]</p>
<p>When objects of non-aggregate class type are
list-initialized ([dcl.init.list]), overload resolution selects the
constructor as follows:</p>
<p>If T has an initializer-list constructor ([dcl.init.list]), the argument list
  consists of the initializer list as a single argument; otherwise, the
 argument list consists of the elements of the initializer list.</p>
<p>For direct-list-initialization, the candidate functions are all
  the constructors of the class of the object being initialized.</p>
<p>For copy-list-initialization, the candidate functions are all the
constructors of that class. However, if an <tt>explicit</tt> constructor is
  chosen, the initialization is ill-formed. [<i>Note:</i> This restriction only
 applies if this initialization is part of the final 
result of overload resolution --<i>end note</i>]
</p>
</blockquote>

<p>In 13.3.3.1p4, change</p>
<blockquote>
However, when considering the argument of a user-defined conversion
function that is a candidate by 13.3.1.3 when invoked for the copying of
the temporary in the second step of a class copy-initialization, <ins>by
[over.match.list] when passing the initializer list as a single argument or
when the initializer list has exactly one element and a conversion to some
class X or reference to (possibly cv-qualified) X is considered for the
first parameter of a constructor of X,</ins> or by 13.3.1.4, 13.3.1.5, or
13.3.1.6 in all cases, only standard conversion sequences and ellipsis
conversion sequences are allowed.
</blockquote>

<p>Add a new section under 13.3.3.1 [over.best.ics]:</p>
<blockquote>
<p>13.3.3.1.5 <b>List-initialization sequence</b> [over.ics.list]</p>
<p>When an argument is an initializer list ([dcl.init.list]), it is
not an expression and special rules apply for converting it to a parameter
type.</p>
<p>If the parameter
type is <tt>std::initializer_list&lt;X&gt;</tt> and all the elements of the
initializer list can be implicitly converted to X, the implicit conversion
sequence is the worst conversion necessary to convert an element of the
list to X. This conversion can be a user-defined conversion even in the
context of a call to an initializer-list constructor.  [ <i>Example:</i>
    </p>
<pre>
  void f(std::initializer_list&lt;int&gt;);
  f( {1,2,3} ); // ok: f(initializer_list&lt;int&gt;) identity conversion
  f( {'a','b'} ); // ok: f(initializer_list&lt;int&gt;) integral promotion
  f( {1.0} ); // error: narrowing

  struct A {
    A(std::initializer_list&lt;double&gt;); // #1
    A(std::initializer_list&lt;complex&lt;double&gt;&gt;); // #2
    A(std::initializer_list&lt;std::string&gt;); // #3
  };
  A a{ 1.0,2.0 }; // ok, uses #1

  void g(A);
  f({ "foo", "bar" }); // ok, uses #3
</pre>
<p>--- end example]</p>
<p>Otherwise, if the parameter is a non-aggregate class X and overload
resolution per [over.match.list] chooses a single best constructor of X to
perform the initialization of an object of type X from the argument
initializer list, the implicit conversion sequence is a user-defined
conversion sequence.
If multiple constructors are viable but none is better than the others,
the implicit conversion sequence is the ambiguous conversion sequence.
User-defined conversions are allowed for conversion
of the initializer list elements to the constructor parameter types except
as noted in 13.3.3.1.

[&nbsp;<i>Example:</i>  </p>
<pre>
  struct A {
    A(std::initializer_list&lt;int&gt;);
  };
  void f(A);
  f( {'a', 'b'} ); // ok: f(A(std::initializer_list&lt;int&gt;)) user-defined conversion

  struct B {
    A(int, double);
  };
  void g(B);
  g( {'a', 'b'} ); // ok: g(B(int,double)) user-defined conversion
  g( {1.0, 1,0} ); // error: narrowing

  void f(B);
  f( {'a', 'b'} ); // error: ambiguous f(A) or f(B)

  struct C {
    C(std::string);
  };
  void h(C);
  h({"foo"}); // ok: h(C(std::string("foo")))

  struct D {
    C(A, C);
  };
  void i(D);
  i({ {1,2}, {"bar"} }); // ok: i(D(A(std::initializer_list&lt;int&gt;{1,2}),C(std::string("bar"))))
</pre>
<p>--- end example]</p>
<p>Otherwise, if the parameter has an aggregate type which can be
initialized from the initializer list according to the rules for aggregate
initialization (8.5.1 [dcl.init.aggr]), the implicit conversion sequence is
a user-defined conversion sequence. [ <i>Example:</i></p>
<pre>
  struct A {
    int m1;
    double m2;
  };

  void f(A);
  f( {'a', 'b'} ); // ok: f(A(int,double)) user-defined conversion 
  f( {1.0} ); // error: narrowing
</pre>
<p>--- end example]</p>
<p>Otherwise, if the parameter is a reference, see 13.3.3.1.4 [over.ics.ref].
[ <i>Note:</i> The rules in this section will apply for initializing the 
underlying temporary for the reference. --<i>end note</i> ] [
<i>Example:</i> </p>
<pre>
  struct A {
    int m1;
    double m2;
  };

 void f(const A&amp;);
 f( {'a', 'b'} ); // ok: f(A(int,double)) user-defined conversion 
 f( {1.0} ); // error: narrowing

 void g(const double &amp;);
 g({1}); // same conversion as int to double
</pre>
<p>--- end example]</p>
<p>Otherwise, if the parameter type is not a class:</p>
<ul>
  <li>
    <p>if the initializer list
has one element, the implicit conversion sequence is the one required
to convert the element to the parameter type;
[ <i>Example:</i>  </p>
<pre>
  void f(int);
  f( {'a'} ); // ok: same conversion as char to int
  f( {1.0} ); // error: narrowing
</pre>
<p>--- end example]</p>
  </li>
  <li>
    <p>if the initializer list
has no elements, the implicit conversion sequence is the identity
conversion. [ <i>Example:</i>  </p>
<pre>
  void f(int);
  f( { } ); // ok: identity conversion 
</pre>
<p>--- end example]</p>
  </li>
</ul>
<p>In all cases other than those enumerated above, no conversion is
possible.</p>
</blockquote>
<p>In 14.5.3 [temp.variadic], paragraph 4, change the first bullet:</p>
<blockquote>
<ul>
  <li>
    <p>In an expression-list (<font color="blue">5.2</font>); the pattern is an 
<del><i>assignment-expression</i></del> <i><ins>initializer-clause</ins></i>.</p>
  </li>
</ul>
</blockquote>
<p>In 14.8.2.1 [temp.deduct.call], paragraph 1:
<blockquote>
<p>Template argument deduction is done by comparing each function template
parameter type (call it P) with the type of the corresponding argument of
the call (call it A) as described below. <ins>If removing references and
cv-qualifiers from P gives <tt>std::initializer_list&lt;P'&gt;</tt> for
some P' and the argument is an initializer list ([dcl.init.list]), then
deduction is performed instead for each element of
the initializer list, taking P' as a function template parameter type and
the initializer element as its argument. Otherwise, an initializer list
argument causes the parameter to be considered a non-deduced context
(<font color="blue">14.8.2.5</font>). [<i>Example:</i></p>
<pre>
  template&lt;class T&gt; void f(std::initializer_list&lt;T&gt;); // #1
  f({1,2,3}); // T deduced to int
  f({1,"asdf"}); // error: T deduced to both int and const char*

  template&lt;class T&gt; void g(T);
  g({1,2,3}); // error: no argument deduced for T
</pre>
<p>--- end example]</p></ins>
<p>For a function parameter pack, ...</p>
</blockquote>
<p>In 14.8.2.5 [temp.deduct.type]
paragraph 5, add as a final bullet at the top level (not the second
bullet level)</p>
<blockquote>
<ul>
  <li>
    <p>A function parameter for which the associated argument is an
      initializer list ([dcl.init.list]) but the parameter does not
      have <tt>std::initializer_list</tt> or reference to possibly
      cv-qualified <tt>std::initializer_list</tt>
      type. [<i>Example:</i></p>
<pre>
  template&lt;class T&gt; void g(T);
  g({1,2,3}); // error: no argument deduced for T
</pre>
<p>--- end example]</p>
  </li>
</ul>
</blockquote>

<p>In 18 [language.support] paragraph 2, change</P>
<blockquote>
The following subclauses describe common type
definitions used throughout the library, characteristics of the
predefined types, functions supporting start and termination of a C++
program, support for dynamic memory management, support for dynamic
type identification, support for exception processing, <ins>support
    for initializer lists,</ins> and other runtime support, as summarized in Table 16.
</blockquote>
<p>...and
add 18.7 Initializer lists <tt>&lt;initializer_list&gt;</tt>
  to Table 16.</p>

<P>Add a new section after 18.7 [support.exception] and 
before 18.8 [support.runtime]:</P>
<blockquote>
  <p>18.8. Initializer lists [support.initlist]</p>

  <p>The header &lt;initializer_list&gt; defines one type.</p>
<pre>
template&lt;class E&gt; class initializer_list {
public:
    initializer_list();

    size_t size() const; // number of elements
    const E* begin() const; // first element
    const E* end() const; // one past the last element
};
</pre>
  <p>An <tt>initializer_list</tt> provides access to an array of objects of
    type <tt>const E</tt>. [ <i>Note:</i> A pair of pointers or a pointer
    plus a length would be obvious representations for <tt>initializer_list</tt>;
    <tt>initializer_list</tt> is used to implement initializer lists as
    specified in [dcl.init.list]. Copying an initializer list does not
    copy the underlying elements. --- <i>end note</i>]</p>

  <p>18.8.1 Initializer list constructors                                           [support.initlist.cons]</p>

  <pre>initializer_list();</pre>

  <p><i>Effects</i>: constructs an empty initializer list<br />
    <i>Postconditions</i>: size() == 0<br />
    <i>Throws</i>: nothing</p>

  <p>18.8.2 Initializer list access                                                   [support.initlist.access]</p>

  <pre>const E* begin() const;</pre>

  <p><i>Returns</i>: a pointer to the beginning of the array; if size()==0
  the value of begin() and end() are unspecified but identical; that is,
  begin()==end().<br />
    <i>Throws</i>: nothing</p>

  <pre>const E* end() const;</pre>

  <p><i>Returns</i>: begin() + size()<br />
    <i>Throws</i>: nothing</p>

  <pre>size_t size() const;</pre>

  <p><i>Returns</i>: the number of elements in the array<br />
    <i>Throws</i>: nothing</p>
</blockquote>

<p>In 20.2 Utility components [utility] paragraph 1:</p>
<blockquote>
<p>This subclause contains some basic function and class templates that are
  used throughout the rest of the library.</p>

<p>Header &lt;utility&gt; synopsis</p>
<pre>
      <ins>#include&lt;initializer_list&gt;</ins>
      namespace std {
</pre>
</blockquote>

</body>
</html>
