<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>P0136R1: Rewording inheriting constructors (core issue 1941 et al)</title>

<style type="text/css">
blockquote.std { color: #000000; background-color: #F1F1F1;
                 border: 1px solid #D1D1D1;
                 padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
                    color: #000000; background-color: #FFEBFF;
                    border: 1px solid #ECD7EC;
                    padding-left: 0.5em; padding-right: 0.5em; }

blockquote.stdins { text-decoration: underline;
                    color: #000000; background-color: #C8FFC8;
                    border: 1px solid #B3EBB3; padding: 0.5em; }

  ins, ins > * { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  del, del > * { text-decoration:line-through; background-color:#FFA0A0 }
  .ins { background-color:#C0FFC0 }

  h3 { margin-top:0 }
</style>

</head>

<body>
<div style="text-align: right; float: right">
ISO/IEC JTC1 SC22 WG21<br>
P0136R1<br>
Richard Smith<br>
richard@metafoo.co.uk<br>
2015-10-19<br>
</div>

<h1>Rewording inheriting constructors (core issue 1941 et al)</h1>

<p>Fixing:</p>
<b><ul>
<li><a href="http://wg21.link/cwg1573">Core Issue 1573</a>: Inherited constructor characteristics
<li><a href="http://wg21.link/cwg1645">Core Issue 1645</a>: Identical inheriting constructors via default arguments
<li><a href="http://wg21.link/cwg1715">Core Issue 1715</a>: Access and inherited constructor templates
<li><a href="http://wg21.link/cwg1736">Core Issue 1736</a>: Inheriting constructor templates in a local class
<li><a href="http://wg21.link/cwg1903">Core Issue 1903</a>: What declarations are introduced by a non-member using-declaration?
<li><a href="http://wg21.link/cwg1941">Core Issue 1941</a>: SFINAE and inherited constructor default arguments
<li><a href="http://wg21.link/cwg1959">Core Issue 1959</a>: Inadvertently inherited copy constructor
<li><a href="http://wg21.link/cwg1991">Core Issue 1991</a>: Inheriting constructors vs default arguments
</ul></b>

<h2>Proposed wording</h2>

<p>
Remove 12.9 class.inhctor, "Inheriting constructors".
</p>

<p>
Change in 3.9 basic.types paragraph 10:
</p>
<blockquote class="std">
A type is a <em>literal type</em> if it is:
<ul><li>&hellip;
    <li>a class type (Clause 9) that has all of the following properties:
      <ul><li>&hellip;
          <li>it is an aggregate type (8.5.1) or has
              at least one <tt>constexpr</tt> constructor or constructor template
              <ins>(possibly inherited (7.3.3) from a base class)</ins>
              that is not a copy or move constructor, and
          <li> &hellip;
      </ul>
</ul>
</blockquote>

<p>
Change in 7.1.5 dcl.constexpr paragraph 5:
</p>
<blockquote class="std">
For a <del>non-template, non-defaulted</del> constexpr function or <del>a non-template, non-defaulted, non-inheriting</del>
constexpr constructor <ins>that is neither defaulted nor a template</ins>, if no argument values exist such that &hellip;
</blockquote>

<p>
Change in 7.3.3 namespace.udecl paragraph 1:
</p>
<blockquote class="std">
A <i>using-declaration</i> introduces a
<del>name</del><ins>set of declarations</ins>
into the declarative region
in which the <i>using-declaration</i> appears.

<pre>
<i>using-declaration</i>:
    using typename<sub>opt</sub> <i>nested-name-specifier unqualified-id</i> ;
</pre>

<ins>
The set of declarations introduced by the <i>using-declaration</i> is found
by performing qualified name lookup (3.4.3, 10.2) for the name in the <i>using-declaration</i>,
excluding functions that are hidden as described below.
If the <i>using-declaration</i> does not name a constructor, the <i>unqualified-id</i>
</ins>
<del>
The member name specified in a <i>using-declaration</i>
</del>
is declared in the declarative region
in which the <i>using-declaration</i> appears
<del>
.
[ Note:
Only the specified name is so declared;
specifying an enumeration name in a <i>using-declaration</i>
does not declare its enumerators in the <i>using-declaration</i>'s declarative region.
&mdash; end note ]

If a <i>using-declaration</i> names a constructor (3.4.3.1), it
implicitly declares a set of constructors in the
class in which the using-declaration appears (12.9);
otherwise the name specified in a using-declaration is
</del>
<ins>as</ins>
a synonym for <del>a set of</del><ins>each</ins> declaration<del>s</del>
<ins>introduced by the <i>using-declaration</i></ins>
<del>in another namespace or class</del>.
<ins>
[ Note:
Only the specified name is so declared;
specifying an enumeration name in a <i>using-declaration</i>
does not declare its enumerators in the <i>using-declaration</i>'s declarative region.
&mdash; end note ]
</ins>
<ins>If the <i>using-declaration</i> names a constructor, it declares that the
class <em>inherits</em> the set of constructor declarations introduced
by the <i>using-declaration</i> from the nominated base class.</ins>
</blockquote>

<p>
Change in 7.3.3 namespace.udecl paragraph 3:
</p>
<blockquote class="std">
In a <i>using-declaration</i> used as a <i>member-declaration</i>, the <i>nested-name-specifier</i> shall name a base class of the
class being defined. If such a <i>using-declaration</i> names a constructor, the <i>nested-name-specifier</i> shall name a
direct base class of the class being defined<del>; otherwise it introduces the set of declarations found by member
name lookup (10.2, 3.4.3.1)</del>. [ Example ]
</blockquote>

<p>
Change in 7.3.3 namespace.udecl paragraph 4:
</p>
<blockquote class="std">
[ Note ]
If <del>an</del><ins> a constructor or</ins> assignment operator brought from a
base class into a derived class <del>scope</del> has the signature of a copy/move
<ins>constructor or</ins> assignment operator for the derived class (12.8),
the <i>using-declaration</i> does not by itself suppress the implicit
declaration of the derived class <del>assignment operator</del><ins>member</ins>;
the <del>copy/move assignment operator</del><ins>member</ins>
from the base class is hidden or overridden by the implicitly-declared
copy/move <ins>constructor or</ins> assignment operator of the derived class,
as described below.
</blockquote>

<p>
Change in 7.3.3 namespace.udecl paragraph 8:
</p>
<blockquote class="std">
A <i>using-declaration</i> <del>for</del><ins>that names</ins> a class member shall be a <i>member-declaration</i>. [ Example ]
</blockquote>

<p>
Change in 7.3.3 namespace.udecl paragraph 11:
</p>
<blockquote class="std">
<ins>[ Note:</ins>
For a <i>using-declaration</i> that names a namespace,</ins>
members added to the namespace after the <i>using-declaration</i> are not <ins>in the set of introduced declarations,
so they are not</ins> considered when a use of the name is made.
<del>[ Note:</del>
Thus, additional overloads &hellip;
</blockquote>

<p>
Change in 7.3.3 namespace.udecl paragraph 15:
</p>
<blockquote class="std">
When a <i>using-declaration</i> brings <del>names</del><ins>declarations</ins>
from a base class into a derived class <del>scope</del>,
member functions and member function templates in the derived class
override and/or hide
member functions and member function templates
with the same name, parameter-type-list (8.3.5), cv-qualification, and <i>ref-qualifier</i> (if any)
in a base class (rather than conflicting).
<ins>Such hidden or overridden declarations are excluded from the set of declarations introduced
by the <i>using-declaration</i>.</ins>
<del>[ Note: For using-declarations that name a constructor, see 12.9. &mdash; end note ]</del>
[ Example:
<pre>
struct B {
&hellip;
}
<ins>
struct B1 {
  B1(int);
};

struct B2 {
  B2(int);
};

struct D1 : B1, B2 {
  using B1::B1;
  using B2::B2;
};
D1 d1(0);    // ill-formed: ambiguous

struct D2 : B1, B2 {
  using B1::B1;
  using B2::B2;
  D2(int);   // OK: D2::D2(int) hides B1::B1(int) and B2::B2(int)
};
D2 d2(0);    // calls D2::D2(int)
</pre>
]
</blockquote>

<p>
Change in 7.3.3 namespace.udecl paragraph 16:
</p>
<blockquote class="std">
For the purpose of overload resolution, the functions
<del>which</del><ins>that</ins> are introduced by a <i>using-declaration</i> into a
derived class <del>will be</del><ins>are</ins> treated as though they were members of the derived class. In particular, the implicit
<tt>this</tt> parameter shall be treated as if it were a pointer to the derived class rather than to the base class.
This has no effect on the type of the function, and in all other respects the function remains a member of
the base class.
<ins>Likewise, constructors that are introduced by a <i>using-declaration</i> are
treated as though they were constructors of the derived class when looking up the
constructors of the derived class (3.4.3.1) or forming a set of
overload candidates (13.3.1.3, 13.3.1.4, 13.3.1.7). If such a constructor is selected
to perform the initialization of an object of class type, all subobjects other than
the base class from which the constructor originated are implicitly initialized
([class.inhctor.init]).</ins>
</blockquote>

<p>
Change in 7.3.3 namespace.udecl paragraph 17:
</p>
<blockquote class="std">
<ins>In a <i>using-declaration</i> that does not name a constructor,
all members of the set of introduced declarations</ins>
<del>The access rules for inheriting constructors are specified in 12.9;
otherwise all instances of the name mentioned in
a <i>using-declaration</i></del> shall be accessible.
<ins>In a <i>using-declaration</i> that names a constructor,
no access check is performed.</ins>
&hellip;
</blockquote>

<p>
Change in 7.3.3 namespace.udecl paragraph 18:
</p>
<blockquote class="std">
<del>The alias</del><ins>A synonym</ins> created by <del>the</del><ins>a</ins> <i>using-declaration</i>
has the usual accessibility for a <i>member-declaration</i>.
<del>
[ Note:
</del>
A <i>using-declaration</i> that names a constructor does not create <del>aliases; see 12.9 for the pertinent accessibility
  rules. — end note ]</del> <ins>a synonym; instead, the additional constructors are
accessible if they would be accessible when used to construct an object of the
corresponding base class, and the accessibility of the <i>using-declaration</i> is ignored.</ins>
[ Example ]
</blockquote>

<p>
Change in 9.2 class.mem paragraph 2:
</p>
<blockquote class="std">
A class is considered a completely-defined object type (3.9) (or complete type) at the closing <tt>}</tt> of the
<i>class-specifier</i>.
Within the class <i>member-specification</i>, the class is regarded as complete within function bodies,
default arguments, <del><i>using-declaration</i>s introducing inheriting constructors (12.9),</del>
<i>exception-specification</i>s,
and <i>brace-or-equal-initializer</i>s for non-static data members
(including such things in nested classes).
Otherwise it is regarded as incomplete within its own class <i>member-specification</i>.
</blockquote>

<i>Drafting note: as observed in core issue 1487, it is not permitted to derive from an incomplete class, and the
  class is not regarded as complete within base-clauses, so this provision doesn't seem useful.</i>

<p>
Change in 10 class.derived paragraph 2:
</p>
<blockquote class="std">
&hellip;
Unless redeclared in the derived class,
members of a base class are also considered to be members of the derived class.
<del>The</del>
<ins>Members of a</ins> base class<del> members</del><ins> other than constructors</ins>
are said to be <em>inherited</em> by the derived class.
<ins>Constructors of a base class can also be inherited as described in 7.3.3.</ins>
Inherited members can be referred to in expressions in the same manner
as other members of the derived class, unless their names are hidden or ambiguous (10.2).
&hellip;
</blockquote>

<p>
Add a new subclause after 12.6.2 class.base.init:
</p>
<blockquote class="stdins">
<h3>12.6.3 Initialization by inherited constructor [class.inhctor.init]</h3>

<ol>
<li>

<p>
When a constructor for type <tt>B</tt> is invoked to initialize an object of
a different type <tt>D</tt> (that is, when the constructor was inherited (7.3.3)),
initialization proceeds as if a defaulted default constructor is used to initialize
the <tt>D</tt> object and each base class subobject from which the constructor was
inherited, except that the <tt>B</tt> subobject is initialized by the invocation
of the inherited constructor.
The complete initialization is considered to be a single function call; in
particular, the initialization of the inherited constructor's parameters is
sequenced before the initialization of any part of the <tt>D</tt> object.
[ Example:
<pre>
struct B1 {
  B1(int, ...) { }
};

struct B2 {
  B2(double) { }
};

int get();

struct D1 : B1 {
  using B1::B1;  // inherits B1(int, ...)
  int x;
  int y = get();
};

void test() {
  D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4),
                 // then d.x is default-initialized (no initialization is performed),
                 // then d.y is initialized by calling get()
  D1 e;          // error: D1 has no default constructor
}

struct D2 : B2 {
  using B2::B2;
  B1 b;
};

D2 f(1.0);       // error: B1 has no default constructor

struct W { W(int); };
struct X : virtual W { using W::W; X() = delete; };
struct Y : X { using X::X; };
struct Z : Y, virtual W { using Y::Y; };
Z z(0); // OK: initialization of Y does not invoke default constructor of X

template&lt;class T&gt; struct Log : T {
  using T::T;    // inherits all constructors from class T
  ~Log() { std::clog &lt;&lt; "Destroying wrapper" &lt;&lt; std::endl; }
};
</pre>
Class template <tt>Log</tt> wraps any class and forwards all of its constructors,
while writing a message to the standard log whenever an object of class
<tt>Log</tt> is destroyed.
]
</p>

<li>
<p>
If the constructor was inherited from multiple base class subobjects of type
<tt>B</tt>, the program is ill-formed.
[ Example:
<pre>
struct A { A(int); };
struct B : A { using A::A; };

struct C1 : B { using B::B; };
struct C2 : B { using B::B; };

struct D1 : C1, C2 {
  using C1::C1;
  using C2::C2;
};

struct V1 : virtual B { using B::B; };
struct V2 : virtual B { using B::B; };

struct D2 : V1, V2 {
  using V1::V1;
  using V2::V2;
};

D1 d1(0); // ill-formed: ambiguous
D2 d2(0); // OK: initializes virtual B base class, which initializes the A base class
          // then initializes the V1 and V2 base classes as if by a defaulted default constructor

struct M { M(); M(int); };
struct N : M { using M::M; };
struct O : M {};
struct P : N, O {};
P p(0); // OK: use M(0) to initialize N's base class,
        // use M() to initialize O's base class
</pre>
]
</p>

<em>Drafting note: This is intended to mirror the behavior when invoking a
non-static member function inherited from multiple base classes.</em>

<li>
<p>When an object is initialized by an inheriting constructor, the principal
constructor (12.6.2, 15.2) for the object is considered to have completed
execution when the initialization of all subobjects is complete.
</p>

</blockquote>

<p>
Do not change 15.2 except.ctor paragraph 3:
</p>
<blockquote class="std">
For an object of class type of any storage duration whose initialization or destruction is terminated by an
exception, the destructor is invoked for each of the object's fully constructed subobjects, that is, for each
subobject for which the principal constructor (12.6.2) has completed execution
and the destructor has not yet begun execution,
except that in the case of destruction,
the variant members of a union-like class are not destroyed. &hellip;
</blockquote>

<p>
Change in 15.2 except.ctor paragraph 4:
</p>
<blockquote class="std">
Similarly, if the <del>non-delegating</del><ins>principal</ins> constructor for an object has completed execution
and a delegating constructor for that object exits with an exception, the object's destructor is invoked. Such destruction is sequenced
before entering a handler of the function-try-block of a delegating constructor for that object, if any.
</blockquote>

<p>
Change in 15.4 except.spec paragraph 15:
<p>
<blockquote class="std">
The <em>set of potential exceptions of an expression</em> <tt>e</tt>
is empty if <tt>e</tt> is a core constant expression (5.20).
Otherwise, it is the union of the sets of potential exceptions
of the immediate subexpressions of <tt>e</tt>,
including default argument expressions used in a function call,
combined with a set <em>S</em> defined by the form of <tt>e</tt>, as follows:

<ul>
<li>If <tt>e</tt> is a function call, &hellip;
<li>If <tt>e</tt> implicitly invokes a function &hellip;
<li><ins>If <tt>e</tt> initializes an object of type <tt>D</tt>
using an inherited constructor for a class of type <tt>B</tt> ([class.inhctor.init]),
<em>S</em> also contains
the sets of potential exceptions of
the implied constructor invocations for subobjects of <tt>D</tt>
that are not subobjects of <tt>B</tt>
(including default argument expressions used in such invocations)
as selected by overload resolution,
and
the sets of potential exceptions of
the initialization of non-static data members
from <i>brace-or-equal-initializer</i>s (12.6.2).</ins>
<li>&hellip;</ul>
</blockquote>

<p>
Change in 15.4 except.spec paragraph 16:
<p>
<blockquote class="std">
Given a<ins>n implicitly-declared special</ins>
member function <tt>f</tt> of some class <tt>X</tt>,
<del>
where <tt>f</tt> is an inheriting constructor (12.9) or an implicitly-declared special member function,
</del>
the <em>set of potential exceptions of the implicitly-declared <ins>special</ins> member function</em>
<tt>f</tt> consists of all the members from the following sets: &hellip;
</blockquote>

<p>
Change in 15.4 except.spec paragraph 17:
<p>
<blockquote class="std">
An <del>inheriting constructor (12.9) and an</del>
implicitly-declared special member function (Clause 12)
<del>are</del><ins>is</ins> considered to have an implicit exception specification,
as follows,
where S is the set of potential exceptions of the implicitly-declared <ins>special</ins> member function.
<ul><li>&hellip;</ul>
<del>
[ Note: An instantiation of an inheriting constructor template has an implied exception specification as if it
were a non-template inheriting constructor. &mdash; end note ]
</del>
[ Example: &hellip; ]
</blockquote>

<p>Add a subclause to Annex C:</p>

<blockquote class="stdins">
<h3>Clause 12: Special member functions [special]</h3>
<b>Change:</b> Inheriting a constructor no longer injects a
constructor into the derived class.<br>
<b>Rationale:</b> Better interaction with other language features.<br>
<b>Effect on original feature:</b>
Valid C++2014 code that uses inheriting constructors may not be valid or may
have different semantics. A <em>using-declaration</em> that names a constructor
now makes the corresponding base class constructors visible to initializations
of the derived class rather than declaring additional derived class constructors.
<pre>
struct A {
  template&lt;typename T> A(T, typename T::type = 0);
  A(int);
};
struct B : A {
  using A::A;
  B(int);
};
B b(42L); // now calls B(int), used to call B&lt;long>(long),
          // which called A(int) due to substitution failure
          // in A&lt;long>(long).
</pre>
</blockquote>

</body></html>
