<html><head>
    <meta http-equiv="Content-Language" content="en-us">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Extension to aggregate initialization</title>
    <style type="text/css">
        body {
            font-size: 12pt;
            font-family: Georgia, Serif;
        }
        p {
        }
        blockquote {
            border: solid thin;
            padding: 1em 1em 1em 1em;
        }

        blockquote.stdins {
            background-color: #CEFFCE;
        }

        blockquote.std {
            background-color: #EFEFEF;

        }

        .std_li {
            padding-bottom: 1em;
        }

        ins {
            color: #005100;
        }

        li {
            padding-bottom: 0.3em;
        }

        pre {
            background-color: #F7F6dc;
            margin-left: 3em;
            margin-right: 3em;
            padding: 1em 1em 1em 1em;
            font-size: 90%;
        }
    </style>
</head>

<body>

  <table style="border-collapse: collapse" border="0" bordercolor="#111111" cellpadding="0" cellspacing="0" width="619">
    <tbody><tr>
      <td align="left" valign="top" width="167">Document number:</td>
      <td width="452">P0017R1</td>
    </tr><tr>
      <td align="left" valign="top" width="167">Date:</td>
      <td width="452">2015-10-24</td>
    </tr>
    <tr>
      <td align="left" valign="top" width="167">Project:</td>
      <td width="452">Programming Language C++, Language Evolution Working Group</td>
    </tr>
    <tr>
      <td align="left" valign="top" width="167">Reply-to:</td>
      <td width="452">Oleg Smolsky 
        &lt;<a href="mailto:oleg.smolsky@gmail.com">oleg.smolsky@gmail.com</a>&gt;
      </td>
    </tr>
  </tbody></table>

<h1>Extension to aggregate initialization</h1>

<h2>I. Introduction</h2>
    <p>C++ supports aggregate initialization, thus allowing the following succinct notation:

    </p><pre>struct user
{
    uint32_t id_;
    std::string name_;
};

user u1{10, "Alice"};
</pre><p></p>

    <p>The Standard states that it is possible to initialize instances 
of such type but places numerous restrictions (such as "no base 
classes"). This paper argues for an amendment to relax the rules and put
 more power (and syntax) into the users' hands. </p>

    <h2>II. Revision history</h2>
    <p>The original paper, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4404.html">N4404</a>
 was discussed in Lenexa and the feedback was generally positive. 
Several EWG members expressed a strong desire to further extend the 
functionality, thus prompting another revision.

</p><h2>III. Motivation</h2>

    <p>There are several cases revolving around inheritance of simple aggregate types that frequently come up:

    </p><ol>
    <li><p>Inheriting from a default-constructible base class.

        </p><p>Comes up when using template-based libraries such as Boost <a href="http://www.boost.org/doc/libs/1_53_0/libs/statechart/doc/index.html">StateChart</a>. The following is needed to define a state with a single member:

</p><pre>struct status_event : boost::statechart::event<status_event>
{
    status_event(uint32 seq) : seq_(seq) {}     // manually written boiler plate
    uint32 seq_;
};</status_event></pre>

        <p>The goal here is to construct a <code>status_event</code> 
instance while writing no boiler plate. So, lets imagine that the base 
class is the first, very special element of the aggregate:

        </p><pre>status_event event{{}, 42};</pre>

    </li><li><p>Inheriting from an aggregate type.

        </p><p>Comes up when people choose to inherit from an aggregate (eg C) type:
</p><pre>struct base
{
    uint32 ibase_;
};

struct derived : base
{
    void f();
};
</pre>

        <p>We want to contruct a <code>derived</code> instance while still explicitly intializing the base clase:

        </p><pre>derived d{{42}};</pre>

    </li></ol>

    <p>As per 8.5.1 [dcl.init.aggr], it is possible to initialize 
instances of simple structs and there are provisions for member structs 
(2), empty members (9) and even brace elision (13). However, Clause (1) 
states that none of this goodness works when there are base classes. 

    </p><p>It would be really useful to extend aggregate initialization rules to cover cases where base classes are present.

</p><h2>IV. Scope</h2>

    <p>Lets consider the following cases:

        </p><ul>
        <li><p>A single base class:
</p><pre>struct base { int a1, a2; };
struct derived : base { int b1; };

derived d1{{1, 2}, 3};      // full explicit initialization
derived d1{{}, 1};          // the base is value initialized
</pre>

            <p>The most-derived type is aggregate-initialized here and so the value <code>b1</code> is reasonably obvious. The base class must be value-initialized in such a case.

        </p></li><li><p>Multiple base classes, mixing user-defined constructors with the compiler-provided ones. 

</p><pre>struct base1 { int b1, b2 = 42; };
struct base2 { 
    B() {
        b3 = 42;
    }
    int b3;
};
struct derived : base1, base2 {
    int d;
};

derived d1{{1, 2}, {}, 4};  // full initialization
derived d2{{}, {}, 4};      // value-initialized bases
</pre>

    The most-derived type is aggregate-initialized, while the base 
classes are initialized with a mix of user-provided constructors, member
 initializers and value initialization.
    </li></ul>

<h2>V. Technical specifications</h2>

<h3>Edit section 8.5.1 "Aggregates [dcl.init.aggr]" </h3>

<p>Modify paragraph 1 (bullets added at CWG's request):

<blockquote class="std">
    <ol>
        <li class="std_li">An <i>aggregate</i> is an array or a class 
(Clause 9) with
<ul>
<li>no user-provided constructors (12.1) <ins>(including those inherited (7.3.3) from a base class)</ins>,
<li> no private or
protected non-static data members (Clause 11),
<li><del>no base classes (Clause 10) and </del>
<li> no virtual functions (10.3)<ins>, and
<li><ins>no virtual, private or protected base classes (10.1).</ins>
</ul>
<ins>
<i>[ Note:</i> Aggregate initialization does not allow accessing protected and private base class'
 members or constructors. <i>-end note ]</i></ins></li>
    </ol>
</blockquote>

<p>Add a new paragraph between the existing paragraphs 1 and 2:

<blockquote class="std">
    <ol start="2">
      <li class="std_li"><ins>
        The <i>elements</i> of an aggregate are:<br>
        -- for an array, the array elements in increasing subscript order<br>
        -- for a class, the direct base classes in declaration order followed by the direct members in declaration order</ins>
      </li>
    </ol>
</blockquote>

<p>Modify the section starting with the existing paragraph 2:

<blockquote class="std">
   
    <ol start="2">
    <li class="std_li">When an aggregate is initialized by an 
initializer list, as specified in 8.5.4, the elements of the initializer
 list are taken as initializers for the <del>members</del> <ins>elements</ins> of the aggregate, in <del>increasing subscript or member</del> order. Each <del>member</del> <ins>element</ins>
 is copy-initialized from the corresponding initializer-clause. If the 
initializer-clause is an expression and a narrowing conversion (8.5.4) 
is required to convert the expression, the program is ill-formed.

<i>[ Note: </i>
If an initializer-clause 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> <i>[ Example:</i>

<pre>struct A {
  int x;
  struct B {
    int i;
    int j;
  } b;
} a = { 1, { 2, 3 } };</pre>

initializes a.x with 1, a.b.i with 2, a.b.j with 3. 

<ins>
<pre>struct base1 { int b1, b2 = 42; };
struct base2 {
    B() {
        b3 = 42;
    }
    int b3;
};
struct derived : base1, base2 {
    int d;
};

derived d1{{1, 2}, {}, 4};
derived d2{{}, {}, 4};
</pre>
</ins>

initializes d1.b1 with 1, d1.b2 with 2, d1.b3 with 42, d1.d with 4 and
 d2.b1 with 0, d2.b2 with 42, d2.b3 with 42, d2.d with 4.

<i>-end example]</i></li>

        <li>[no change]</li>
        <li>[no change]</li>
        <li>[no change]</li>
        <li>[no change]</li>

        <li>If there are fewer initializer-clauses in the list than there are <del>members</del> <ins>elements</ins> in the aggregate, then each <del>member</del> <ins>element</ins>
 not explicitly initialized shall be initialized from its 
brace-or-equal-initializer or, if there is no 
brace-or-equal initializer, from an empty initializer list (8.5.4).</li>

        <li>[no change]</li>

        <li>If an aggregate class C contains a subaggregate <del>member <b>m</b></del> <ins>element <b>e</b></ins> that has no members for purposes of aggregate initialization, the initializer-clause for <del><b>m</b></del> <ins><b>e</b></ins> shall not be omitted from an initializer-list for an object of type C 
unless the initializer-clauses for all members of C following <del><b>m</b></del> <ins><b>e</b></ins> are also omitted.

        </li><li>[no change]
        </li><li>[no change]

        </li><li>Braces can be elided in an initializer-list as follows.
 If the initializer-list begins with a left brace, then the succeeding 
comma-separated list of initializer-clauses initializes the <del>members</del> <ins>elements</ins> of a subaggregate; it is erroneous for there to be more initializer-clauses than <del>members</del> <ins>elements</ins>.
 If, however, the initializer-list for a subaggregate does not begin 
with a left brace, then only enough initializer-clauses from the list 
are taken to initialize the <del>members</del> <ins>elements</ins> of the subaggregate; any remaining initializer-clauses are left to initialize the next <del>member</del> <ins>element</ins> of the aggregate of which the current subaggregate is <del>a member</del> <ins>an element</ins>.

        </li><li>All implicit type conversions (Clause 4) are considered
 when initializing the <del>aggregate member</del> <ins>element</ins> with an assignment-expression. 
If the assignment-expression can initialize <del>a member</del> <ins>an element</ins>, the <del>member</del> <ins>element</ins> is initialized. Otherwise, if the <del>member</del> <ins>element</ins>
 is itself a subaggregate, brace elision is assumed and the 
assignment-expression is considered for the initialization of the first <del>member</del> <ins>element</ins> of the subaggregate. <i>[ Note:</i> As specified above, brace elision cannot apply to subaggregates with no <del>members</del> <ins>elements</ins> for purposes of aggregate initialization; an initializer-clause for the entire subobject is required. <i>-end note ]</i>

<p><i>[ Example:</i>

<pre>
struct A {
  int i;
  operator int();
};
struct B {
  A a1, a2;
  int z;
};
A a;
B b = { 4, a, a };
</pre>
<br>Braces are elided around the initializer-clause for b.a1.i. b.a1.i is initialized with 4, b.a2 is initialized
with a, b.z is initialized with whatever a.operator int() returns. <i>-end example ]</i>

        </li>

    <li><i>Note:</i> An aggregate array or an aggregate class may contain <del>members</del> <ins>elements</ins> of a class type with a user-provided constructor (12.1). Initialization of these aggregate objects is described in 12.6.1. <i>-end note ]</i>
    </li>
    </li><li>[no change]
    </li><li>[no change]
    </li><li>[no change]

    </ol>
    </blockquote>


<h3>Add a subsection to C.4 "
C++ and ISO C++ 2014 [diff.cpp14]" </h3>

    <blockquote class="std">
    <ins>
    <p><b>C.4.2 Clause 3: aggregates</b>
    <p>8.5.1<br>
<b>Change:</b> definition of an aggregate is extended to apply to user-defined types with base 
classes.<br>
<b>Rationale:</b> to increase convenience of aggregate-initialization.<br>
<b>Effect on original feature:</b> It is now necessary to explicitly initialize the
 base as per the following example:
<pre>
struct derived;
struct base {
  friend struct derived;
private: 
  base();
};
struct derived : base {};

derived d1{};       // Error. The code was well-formed before.
derived d2;         // still OK

</pre>
    </ins>
    </blockquote>

<h2>VI. Acknowledgments</h2>

  I want to thank Richard Smith for the early feedback as well as enormous specification help.



</body></html>
