<html>
<head><title>N2628 - Non-static data member initializers</title></head>
<body>
<table border=0>
<tr>
  <td><b>Doc No:</b></td>
  <td>N2628=08-0138</td>
</tr>
<tr>
  <td><b>Date:</b></td>
  <td>2008-05-13</td>
</tr>
<tr>
  <td><b>Reply to:</b>&nbsp;</td>
  <td>Bill Seymour &lt;stdbill.h@pobox.com&gt;</td>
</tr>
</table>

<center>

<h1>Non-static data member initializers</h1>
<h3>Michael Spertus<br/>Bill Seymour</h3>
</center>

<h2>Abstract</h2>

We propose allowing the use of initializers for non-static class and
struct data members. The purpose of this is to increase maintainability,
reduce the risk of subtle errors in complex program code, and to make the
use of initializers more consistent.

<p><hr size=5>

<h2>Acknowledgement</h2>

The authors would like to thank Jens Maurer for his many excellent
suggestions regarding the words for the Standard.  Thanks also to
Bjarne Stroustrup for several excellent suggestions making reference
to <tt><b>{}</b></tt> initializers in the rationale portion of this paper.
If any problems remain, this paper&rsquo;s authors are at fault.

<p><hr size=5>

<h2>The proposal</h2>

The basic idea is to allow non-static data members of class types to be
initialized where declared. The goal is that all of the same initialization
syntaxes may be used as for initialization of local variables; and other analyses and suggestions for
improving initialization of local variables as in
<a name="initdocs">
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/N1493.pdf">N1493</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/N1509.pdf">N1509</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/N1584.pdf">N1584</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/N1701.pdf">N1701</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/N1806.html">N1806</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/N1824.htm">N1824</a>, and
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/N1919.pdf">N1919</a>
</a>
may also be applied <i>mutatis mutandis</i> to non-static <tt>class</tt> data members.
This goal will not be reached completely, however, because to avoid parsing problems,
we no longer propose to allow initializers of the
<nobr>&ldquo;<tt><b>(</b></tt> <i>expression-list</i> <tt><b>)</b></tt>&rdquo;</nobr>
form <a href="#konaissue">as explained below</a>.  On the other hand, there now
seems to be a consensus on the use of <tt><b>{}</b></tt> for initializers
(<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2575.pdf">N2575</a>),
so we use that form for some examples that used parentheses in earlier
versions of this paper.<!--  Initializers of that form
remain in the examples immediately below, however, to preserve some history.)-->

<p>As a simple example,
<pre>
    class A {
    public:
        int a = 7;
    };
</pre>
would be equivalent to
<pre>
    class A {
    public:
        A() : a(7) {}
    };
</pre>
The real benefits of member initializers do not become apparent until a class
has multiple constructors. For many data members, especially private ones, all
constructors initialize a data member to a common value as in the next example:
<pre>
    class A {
    public:
        A(): a(7), b(5), hash_algorithm("MD5"), s("class A example") {}
        A(int a_val) : a(a_val), b(5), hash_algorithm("MD5"), s("Constructor run") {}
        A(int b_val) : a(7), b(b_val), hash_algorithm("MD5"), s("Constructor run") {}
        A(D d) : a(f(d)), b(g(d)), hash_algorithm("MD5"), s("Constructor run") {}
        int a, b;
    private:
        // Cryptographic hash to be applied to all A instances
        HashingFunction hash_algorithm;
        // String indicating state in object lifecycle
        std::string s;
    };
</pre>
Even in this simple example, the redundant code is already problematic if the
constructor arguments for <tt>hash_algorithm</tt> are copied incorrectly in one of
<tt>A</tt>&rsquo;s constructors or if one of the lifecycle states was accidentally misspelled as
<tt>"Constructor Run"</tt>. These kinds of errors can easily result in subtle bugs.
Such inconsistencies are readily avoided using member initializers.
<pre>
    class A {
    public:
        A(): a(7), b(5) {}
        A(int a_val) : a(a_val), b(5) {}
        A(int b_val) : a(7), b(b_val) {}
        A(D d) : a(f(d)), b(g(d)) {}
        int a, b;
    private:
        // Cryptographic hash to be applied to all A instances
        HashingFunction hash_algorithm("MD5");
        // String indicating state in object lifecycle
        std::string s("Constructor run");
    };
</pre>

Not only does this eliminate redundant code that must be manually synched, it
makes much clearer the distinctions between the different constructors.
(Indeed, in Java, where both forms of initialization are available,
the use of member initializers is invariably preferred by experienced
Java programmers in examples such as these.)

<p>Now suppose that it is decided that MD5 hashes are not collision resistent
enough and that SHA-1 hashes should be used. Without member initializers, all
the constructors need to be updated. Unfortunately, if one developer is unaware
of this change and creates a constructor that is defined in a different source
file and continues to initialize the cryptographic algorithm to MD5, a very hard
to detect bug will have been introduced. It seems better to keep the information
in one place.

<p>It may happen that a data member will usually have a particular value, but a
few specialized constructors will need to be cognizant of that value. If a
constructor initializes a particular member explicitly, the constructor initialization
overrides the member initializations as shown below:
<pre>
    class A {
    public:
        A(): a(7), b(5) {}
        A(int a_val) : a(a_val), b(5) {}
        A(int b_val) : a(7), b(b_val) {}
        A(D d) : a(f(d)), b(g(d)) {}
        // Copy constructor
        A(const A& aa) : a(aa.a),
                         b(aa.b),
                         hash_algorithm(aa.hash_algorithm.getName()),
                         s(aa.s) {}
        int a, b;
    private:
        // Cryptographic hash to be applied to all A instances
        HashingFunction hash_algorithm("MD5");
        // String indicating state in object lifecycle
        std::string s("Constructor run");
    };
</pre>
A few additional points are worth noting.
<ul>
<li>By allowing non-static data members of classes to be initialized in the same
    way as non-static local variables (which should be thought of as non-static
    data members of the function frame), C++ initialization becomes more
    consistent. As many of the <a href="#initdocs">documents mentioned above</a>
    point out, this is much needed.
<p><li>Because these initializers must be given in the class definition, which
    may be included in many files, it is possible that the initializers may vary
    in value depending on context. Although this is troublesome, such ODR
    problems already exist for default arguments, inline methods, member
    types, etc.; and member initializers do not appreciably aggravate them.
<p><li>There is some overlap between this proposal and constructor delegation and forwarding
    (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/N1445.htm">N1445</a>,
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/N1581.pdf">N1581</a>,
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/N1618.pdf">N1618</a>, and
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/N1898.pdf">N1898</a>).
    However, it is easy to see that neither technique obviates the other. For example,
    overriding member initializers appears difficult to do in generality through
    constructor forwarding.  (And note that Java has both member initialization and
    constructor forwarding.  This is not regarded as confusing, and most experienced
    Java programmers make regular use of both techniques based on applicability.)
<p><li>Member initializers make possible the use of copy-initialization for class
    data members. It seems likely this flexibility will prove useful just as in the
    case of local variables.
<p><li>It is intended that this proposal also supports initializer lists
    (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2575.pdf">N2575</a>)
    if they are adopted into C++0X.
</ul>

<p><a name="konaissue"><hr size=3></a>

<h3>An issue raised in Kona regarding scope of identifiers:</h3>

<p>During discussion in the Core Working Group at the September &rsquo;07 meeting in Kona,
a question arose about the scope of identifiers in the initializer.  Do we want to allow
class scope with the possibility of forward lookup; or do we want to require that the initializers
be well-defined at the point that they&rsquo;re parsed?

<h4>What&rsquo;s desired:</h4>

The motivation for class-scope lookup is that we&rsquo;d like to be able to put
anything in a non-static data member&rsquo;s initializer that we could put
in a <i>mem-initializer</i> without significantly changing the semantics
(modulo direct initialization vs. copy initialization):
<pre>
    int x();

    struct S {
        int i;
        S() : i(x()) {} // currently well-formed, uses S::x()
        // ...
        static int x();
    };

    struct T {
        int i = x(); // should use T::x(), ::x() would be a surprise
        // ...
        static int x();
    };
</pre>

<h4>Problem 1:</h4>

Unfortunately, this makes initializers of the
<nobr>&ldquo;<tt><b>(</b></tt> <i>expression-list</i> <tt><b>)</b></tt>&rdquo;</nobr>
form ambiguous at the time that the declaration is being parsed:
<pre>
    struct S {
        int i(x); // data member with initializer
        // ...
        static int x;
    };

    struct T {
        int i(x); // member function declaration
        // ...
        typedef int x;
    };
</pre>

One possible solution is to rely on the existing rule that, if a declaration
could be an object or a function, then it&rsquo;s a function:
<pre>
    struct S {
        int i(j); // ill-formed...parsed as a member function,
                  // type j looked up but not found
        // ...
        static int j;
    };
</pre>

A similar solution would be to apply another existing rule,
currently used only in templates, that if <tt>T</tt> could
be a type or something else, then it&rsquo;s something else;
and we can use &ldquo;<tt>typename</tt>&rdquo; if we really
mean a type:
<pre>
    struct S {
        int i(x); // unabmiguously a data member
        int j(typename y); // unabmiguously a member function
    };
</pre>

Both of those solutions introduce subtleties that are likely
to be misunderstood by many users (as evidenced by the many
questions on comp.lang.c++ about why
<nobr>&ldquo;<tt>int</tt> <tt>i();</tt>&rdquo;</nobr>
at block scope doesn&rsquo;t declare a default-initialized <tt>int</tt>).

<p>The solution proposed in this paper is to allow only initializers of the
&ldquo;<tt><b>=</b></tt>&nbsp;<i>initializer-clause</i>&rdquo;
and &ldquo;<b>{</b>&nbsp;<i>initializer-list</i>&nbsp;<b>}</b>&rdquo; forms.
That solves the ambiguity problem in most cases, for example:
<pre>
    HashingFunction hash_algorithm{"MD5"};
</pre>
Here, we could not use the <tt><b>=</b></tt> form because HasningFunction&rsquo;s
constructor is <tt>explicit</tt>.

<p>In especially tricky cases, a type might have to be mentioned twice.  Consider:
<pre>
    vector&lt;int&gt; x = 3; // error:  the constructor taking an int is explicit
    vector&lt;int&gt; x(3);  // three elements default-initialized
    vector&lt;int&gt; x{3};  // one element with the value 3
</pre>
In that case, we have to chose between the two alternatives by using the
appropriate notation:
<pre>
    vector&lt;int&gt; x = vector&lt;int&gt;(3); // rather than vector&lt;int&gt; x(3);
    vector&lt;int&gt; x{3}; // one element with the value 3
</pre>

<h4>Problem 2:</h4>

Another issue is that, because we propose no change to the rules for initializing
static data members, adding the <tt>static</tt> keyword could make a well-formed
initializer ill-formed:
<pre>
    struct S {
               const int i = f(); // well-formed with forward lookup
        static const int j = f(); // always ill-formed for statics
        // ...
        constexpr static int f() { return 0; }
    };
</pre>

<h4>Problem 3:</h4>

A third issue is that class-scope lookup could turn a compile-time error
into a run-time error:
<pre>
    struct S {
        int i = j; // ill-formed without forward lookup, undefined behavior with
        int j = 3;
    };
</pre>
(Unless caught by the compiler, <tt>i</tt> might be intialized
with the undefined value of <tt>j</tt>.)

<h4>The proposal:</h4>

CWG had a 6-to-3 straw poll in Kona in favor of class-scope lookup;
and that is what this paper proposes, with initializers
for non-static data members limited to the
<nobr>&ldquo;<tt><b>=</b></tt> <i>initializer-clause</i>&rdquo;</nobr> form.
We do not list changes related to the <tt><b>{}</b></tt> form
of initializers since that&rsquo;s a separate proposal; but we see
no problems integrating those two proposals and assume that it will be done.

<p>We believe:
<blockquote>
<b>Problem 1:</b>  This problem does not occur as we don&rsquo;t propose the
<tt><b>()</b></tt> notation.  The <tt><b>=</b></tt> and <tt><b>{}</b></tt>
initializer notations do not suffer from this problem.
<p><b>Problem 2:</b>  adding the <tt>static</tt> keyword makes a number
of differences, this being the least of them.
<p><b>Problem 3:</b>  this is not a new problem, but is the same
order-of-initialization problem that
already exists with constructor initializers.
</blockquote>

<p><a name="autoreasons"><hr size=3></a>

<h3>A recent issue regarding <tt>auto</tt>:</h3>

One national body dislikes allowing the <tt>auto</tt>
<nobr><i>type-specifier</i></nobr> for
<nobr>non-<tt>static</tt>s.</nobr>
From an e-mail to the authors:

<blockquote>
<blockquote>
<pre>
template&lt; class T &gt;
struct MyType : T {
  auto data = func();
  static const size_t erm = sizeof(data);
};
</pre>
</blockquote>

In order to determine the layout of X, we now have 2-phase name lookup and ADL.
Note that func could be either a type or a function; it may be found
in T,
the namespace of MyType, the associated namespace(s) of T when instantiated,
the global namespace, an anonymous namespace, or any namespaces subject to
a using directive.  With care we could probably throw some concept_map lookup
in for luck.

<p>Depending on the order of header inclusion I might even get different results
for ADL, and break the One Definition Rule - which is not required to be diagnosed.
</blockquote>

Because of this controversy, the authors no longer propose that <tt>auto</tt>
be allowed for non-<tt>static</tt> data members.

<p><hr size=5>

<h2>
  Suggested changes to the Working Paper,
  <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588">N2588</a>
</h2>

<h4>5.1 Primary expressions [expr.prim]</h4>

Change 5.1p3:

<blockquote>
The keyword <tt>this</tt> names a pointer to the object for which a non-static member
function (9.3.2) is invoked <ins>or a non-static data member&rsquo;s initializer (9.2)
is evaluated</ins>.
The keyword <tt>this</tt> shall be used only inside
a non-static class member function body (9.3) <ins>or in an
<nobr><i>assignment-initializer</i></nobr> for
a non-static data member (9.2)</ins>.  The type of the expression is a pointer
to the function&rsquo;s <ins>or non-static data member&rsquo;s</ins> class <del>(9.3.2)</del>,
possibly with <nobr>cv-qualifiers</nobr> on the class type.  The expression is an rvalue.
</blockquote>

<p><hr>

Add a bullet to 5.1p11:

<blockquote>
An <i>id-expression</i> that denotes a non-static data member or
non-static member function of a class can only be used:
<blockquote>
&mdash; as part of a class member access (5.2.5) in which the
object-expression refers to the member&rsquo;s class or a class
derived from that class, or
<p>&mdash; to form a pointer to member (5.3.1), or
<p>&mdash; in the body of a non-static member function of that class
or of a class derived from that class (9.3.1), or
<p>&mdash; in a <i>mem-initializer</i> for a constructor for that class or
for a class derived from that class (12.6.2), or
<p><ins>&mdash; in an <nobr><i>assignment-initializer</i></nobr>
for a non-static data member of that class or
of a class derived from that class (12.6.2), or</ins>
<p>&mdash; if that <i>id-expression</i> denotes a non-static data member
and it is the sole constituent of an unevaluated operand,
except for optional enclosing parentheses. [ Example:
<br>...
</blockquote>
</blockquote>

<p><a name="autochange"><hr size=3></a>

<h4>7.1.6.4 <tt>auto</tt> specifier [dcl.spec.auto]</h4>

<p>Change paragraph 4:
<blockquote>
The <tt>auto</tt> <i>type-specifier</i> can also be used in declaring an object
in the <i>condition</i> of a selection statement (6.4) or an iteration statement (6.5),
in the <i>type-specifier-seq</i> in a <i>new-type-id</i> (5.3.4), and in declaring
a static data member with
<del>a <nobr><i>constant-initializer</i></nobr></del>
<ins>an <nobr><i>assignment-initializer</i></nobr></ins>
that appears within the <nobr><i>member-specification</i></nobr> of a class definition (9.4.2).
</blockquote>

<p><hr size=3>

<h4>8.5 Initializers [dcl.init]</h4>


Change the grammar for initializer:

<blockquote>

<i>initializer:</i><br>

<tt>&nbsp;&nbsp;&nbsp;&nbsp;</tt><del><b>=</b>&nbsp;&nbsp;<i>initializer-clause</i></del>&nbsp;&nbsp;<ins><i>assignment-initializer</i></ins><br>

<tt>&nbsp;&nbsp;&nbsp;&nbsp;</tt><tt><b>(</b></tt>&nbsp;&nbsp;<i>expression-list</i>&nbsp;&nbsp;<tt><b>)</b></tt>

<p><ins><i>assignment-initializer:</i></ins><br>

<tt>&nbsp;&nbsp;&nbsp;&nbsp;</tt><ins><tt><b>=</b></tt>&nbsp;&nbsp;<i>initializer-clause</i></ins>
</blockquote>

<p><hr>

Add to 8.5p12:

<blockquote>
The initialization that occurs in argument passing, function return, throwing an exception (15.1),
handling an exception (15.3), <ins>initializing non-static data members with
<nobr><i>assignment-initializer</i>s,</nobr></ins>
and <nobr>brace-enclosed</nobr> initializer lists (8.5.1)
is called <nobr><i>copy-initialization</i></nobr> and is equivalent to the form
<blockquote>
<tt>T x = a;</tt>
</blockquote>
</blockquote>

<p><hr>

Change &ldquo;base and member initializers&rdquo; to &ldquo;<i>mem-initializers</i>&rdquo; in 8.5p13:

<blockquote>
The initialization that occurs in <tt>new</tt> expressions (5.3.4),
<tt>static_cast</tt> expressions (5.2.9), functional notation type conversions (5.2.3),
and <del>base and member initializers</del> <ins><i>mem-initializers</i></ins> (12.6.2)
is called <i>direct-initialization</i> and is equivalent to the form
<blockquote>
<tt>T x(a);</tt>
</blockquote>
</blockquote>

<p><hr size=3>
<h4>9.2 Class members [class.mem]</h4>

Change <i>constant-initializer</i> to <i>assignment-initializer</i> in the second line of <i>member-declarator</i>:

<blockquote>
<i>member-declarator:</i>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>declarator&nbsp;&nbsp;pure-specifier<small><sub>opt</sub></small></i>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>declarator&nbsp;&nbsp;<del>constant</del><ins>assignment</ins>-initializer<small><sub>opt</sub></small></i>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>identifier<small><sub>opt</sub></small></i>&nbsp;&nbsp;<tt>:</tt>&nbsp;&nbsp;<i>constant-expression</i>
</blockquote>

<p><hr>

Delete the final rule entirely:
<blockquote>
<del><i>constant-initializer</i>:</del><br><tt>&nbsp;&nbsp;&nbsp;&nbsp;</tt><del>= <i>constant-expression</i></del>
</blockquote>

<p><hr>

Add to 9.2p2:

<blockquote>
A class is considered a completely-defined object type (3.9) (or complete type) at the closing
<b><tt>}</tt></b> of the <nobr><i>class-specifier</i>.</nobr>
Within the class <nobr><i>member-specification</i>,</nobr>
the class is regarded as complete within function bodies, default arguments,
<nobr><i>exception-specification</i>s<ins>,</nobr> and non-static data member
<nobr><i>assignment-initializer</i>s</nobr></ins> (including such things in nested classes).
Otherwise it is regarded as incomplete within its own
class <nobr><i>member-specification</i>.</nobr>
</blockquote>

<p><hr>

Delete 9.2p4 entirely:
<blockquote>
<del>A <i>member-declarator</i> can contain a <i>constant-initializer</i> only if it declares
a <tt>static</tt> member (9.4) of <tt>const</tt> literal type, see 9.4.2.</del>
</blockquote>

<p><hr size=3>

Add a new paragraph after the new 9.2p4 (which was p5 before the deletion
immediately above):

<blockquote>
<ins>A member can be initialized using an <nobr><i>assignment-initializer</i>.</nobr>
(For static data members, see 9.4.2 [class.static.data]; for non-static
data members, see 12.6.2 [class.base.init]).</ins>
<!--<ins>A non-static data member with an <nobr><i>assignment-initializer</i></nobr> will be
initialized by the constructor.</ins>-->
</blockquote>

<p><hr size=3>

<h4>9.4.2 Static data members [class.static.data]</h4>

Change 9.4.2p3:

<blockquote>
<del>If a static data member is of <tt>const</tt> literal type, its declaration in the class definition
can specify a <nobr><i>constant-initializer</i>.</nobr></del>
<ins>A declaration of a <tt>static</tt> data member in a class definition
may only specify an <nobr><i>assignment-initializer</i></nobr>
if that data member is of <tt>const</tt> literal type, in which case
the <nobr><i>initializer-clause</i></nobr> shall be an integral constant
expression (5.19).</ins>
A <tt>static</tt> data member of literal type can be declared in the class definition
with the <tt>constexpr</tt> specifier; if so, its declaration shall specify
<del>a <nobr><i>constant-initializer</i></nobr></del> <ins>an <nobr><i>assignment-initializer</i></nobr>
with an <nobr><i>initializer-clause</i></nobr> that is an integral constant expression (5.19)</ins>.
<del>In both these cases, the member</del>
<ins>A <tt>static</tt> data member that is of <tt>const</tt> literal type,
or that is declared with the <tt>constexpr</tt> specifier,</ins> may appear in integral constant expressions.
The member shall still be defined in a namespace scope if it is used in the program<ins>;</ins>
and <ins>if the <nobr><i>member-declarator</i></nobr> contains an
<nobr><i>assignment-initializer</i></nobr>,</ins> the namespace scope definition
shall not contain an <i>initializer</i>.
</blockquote>

<p><hr size=3>

<h4>12.1 Constructors [class.ctor]</h4>

Add a new bullet between the first and second in 12.1p5:

<blockquote>
A <i>default</i> constructor for a class X is a constructor of class X that can be called
without an argument. If there is no user-declared constructor for class X,
a default constructor is implicitly declared.  An implicitly-declared default constructor is
an <tt>inline</tt> <tt>public</tt> member of its class. A default constructor is <i>trivial</i>
if it is not user-provided (8.4) and if:
<blockquote>
<p>&mdash; its class has no virtual functions (10.3) and no virtual base classes (10.1), and
<p><ins>&mdash; no non-static data member of its class has an <nobr><i>assignment-initializer</i>,</nobr>
and</ins> <p>&mdash; all the direct base classes of its class have trivial default constructors, and
<p>&mdash; for all the non-static data members of its class that are of class type
(or array thereof), each such class has a trivial default constructor.
</blockquote>
</blockquote>

<p><hr size=3>

<h4>12.6.2 Initializing bases and members [class.base.init]</h4>

<p>Add a new first bullet to 12.6.2p4:

<blockquote>
If a given non-static data member or base class is not named by a
<nobr><i>mem-initializer-id</i></nobr>
(including the case where there is no
<nobr><i>mem-initializer-list</i></nobr> because the constructor
has no <nobr><i>ctor-initializer</i>),</nobr></ins> then
<blockquote>
<ins>&mdash; If the entity is a non-static data member
that has an <nobr><i>assignment-initializer</i>,</nobr>
the entity is copy-initialized with the value of the
<nobr><i>initializer-clause</i>.</nobr></ins>
<p>
&mdash; <del>If</del> <ins>Otherwise, if</ins> the entity is a non-static ...
</blockquote>
</blockquote>

<p><hr>

And add &ldquo;nor copy-initialized&rdquo; to the last part of 12.6.2p4:

<blockquote>
After the call to a constructor for class X has completed,
if a member of X is neither specified in the constructor&rsquo;s
<i>mem-initializers</i>, <ins>nor copy-initialized,</ins> nor default-initialized,
nor value-initialized, nor given a value during execution of the <i>compound-statement</i>
of the body of the constructor, the member has indeterminate value.
</blockquote>

<p><hr>

Add a new paragraph 5 and an example after 12.6.2p4:
<blockquote>
<ins>If a given non-static data member has both an <nobr><i>assignment-initializer</i></nobr>
and a <nobr><i>mem-initializer</i>,</nobr>
the initialization specified by the <nobr><i>mem-initializer</i></nobr> is performed,
and the non-static data member&rsquo;s <nobr><i>assigmnent-initializer</i></nobr> is ignored.
<p>[ <i>Example:</i> given</ins>
<pre>
<ins>struct A {</ins>
    <ins>int i = /* some integer expression with side effects */ ;</ins>
    <ins>A(int arg) : i(arg) { }</ins>
    <ins>// ...</ins>
<ins>};</ins>
</pre>
<ins>the <tt>A(int)</tt> constructor will simply initialize <tt>i</tt> to the value
of <tt>arg</tt>, and the side effects in <tt>i</tt>&rsquo;s
<nobr><i>assigmnent-initializer</i></nobr>
will not take place. &mdash; <i>end example</i> ]</ins>
</blockquote>

<p><hr size=3>

<h4>12.7 Construction and destruction [class.cdtor]</h4>

Add &ldquo;<i>assignment-initializer</i> or&rdquo; in the second sentence of 12.7p4:

<blockquote>
Member functions, including virtual functions (10.3), can be called
during construction or destruction (12.6.2). When a
virtual function is called directly or indirectly from a constructor
(including from the <ins><nobr><i>assignment-initializer</i></nobr> or</ins>
<nobr><i>mem-initializer</i></nobr>
for a data member) or from a destructor, and the object to which the call
applies is the object under construction or destruction, the function
called is the one defined in the constructor or destructor&rsquo;s own class
or in one of its bases, but not a function overriding it in a class derived
from the constructor or destructor&rsquo;s class, or overriding it in one of
the other base classes of the most derived object (1.8). If the virtual
function call uses an explicit class member access (5.2.5) and the
object-expression refers to the object under construction or destruction
but its type is neither the constructor or destructor&rsquo;s own class or
one of its bases, the result of the call is undefined. [ Example:
<br>...
</blockquote>

<p><hr>

<p>Same for 12.7p5:
<blockquote>
The <tt>typeid</tt> operator (5.2.8) can be used during construction
or destruction (12.6.2). When <tt>typeid</tt> is used in a constructor
(including from the <ins><nobr><i>assignment-initializer</i></nobr> or</ins>
<nobr><i>mem-initializer</i></nobr>
for a data member) or in a destructor, or used in a function called
(directly or indirectly) from a constructor or destructor, if the operand
of <tt>typeid</tt> refers to the object under construction or destruction,
<tt>typeid</tt> yields the <tt>std::type_info</tt> object representing
the constructor or destructor&rsquo;s class. If the operand of <tt>typeid</tt>
refers to the object under construction or destruction and the static type
of the operand is neither the constructor or destructor&rsquo;s class
nor one of its bases, the result of <tt>typeid</tt> is undefined.
</blockquote>

<p><hr>

<p>And for 12.7p6:
<blockquote>
<tt>Dynamic_cast</tt>s (5.2.7) can be used during construction or destruction (12.6.2).
When a <tt>dynamic_cast</tt> is used in a constructor (including from the
<ins><nobr><i>assignment-initializer</i></nobr> or</ins>
<nobr><i>mem-initializer</i></nobr> for a data member)
or in a destructor, or used in a function called (directly or indirectly)
from a constructor or destructor, if the operand of the <tt>dynamic_cast</tt>
refers to the object under construction or destruction, this object is considered
to be a most derived object that has the type of the constructor or destructor&rsquo;s
class. If the operand of the <tt>dynamic_cast</tt> refers to the object under
construction or destruction and the static type of the operand is not a pointer
to or object of the constructor or destructor&rsquo;s own class or one of its bases,
the <tt>dynamic_cast</tt> results in undefined behavior.
</blockquote>

<p><hr size=3>

<h4>12.8 Copying class objects [class.copy]</h4>

Add a note after the first sentence of 12.8p8:
<blockquote>
The implicitly-defined or explicitly-defaulted copy constructor for class X performs
a memberwise copy of its subobjects. <ins>[ <i>Note:</i>
<nobr><i>assignment-initializers</i></nobr> of non-static data members are ignored.
See also the example in 12.6.2p5. &mdash; <i>end note</i> ]</ins>
The order of copying is the same as the order of initialization of bases and members
in a user-defined constructor (see 12.6.2). Each subobject is copied in the manner
appropriate to its type:
</blockquote>

<p><hr size=5>
</body>
</html>
