<html>
<head>
<title>N2254 Inheriting Constructors (revision)</title>
</head>

<body>
Document Number: N2254=07-0114<br/>
2007-05-05<br/>
Alisdair Meredith &lt;alisdair.meredith@uk.renaultf1.com><br/>
Michael Wong &lt;michaelw@ca.ibm.com><br/>
Jens Maurer &lt;Jens.Maurer@gmx.net><br/>

<h1>Inheriting Constructors (revision 1)</h1>

This paper is a revision of N2203 "Inheriting Constructors" by
Alisdair Meredith, Michael Wong, Jens Maurer.


<h2>Problem Description</h2>

There is often a desire to initialize a derived class with exactly the same set
of constructors as its base.  This typically ends up with a series of tediously
simply forwarding declarations and definitions.  This work could be more easily
handled by the compiler, is less error-prone when handled by the compiler, and
the intent is clearer to read if the forwarding problem can be reduced to a
single statement.
<p>
There are also a couple of cases where the forwarding constructors cannot be
declared by the user, such as for a dependant base class where a class
template derives from one (or more) of its own template type parameters.
<p>
<h2>Outline of the Solution</h2>

Initial analysis was supplied by Francis Glassborow (N1583) and after
further feedback from the evolution group, the direction was to word the
simplest feature possible without making any effort to support extended
use cases. The more complicated examples will probably be handled by a
different language feature - a variadic constructor template.
<p>
The basic idea is to extend using declarations to support constructors.  This
falls out of the grammar today (no grammar changes required) and simply extends
the semantic rules to cover the new case.
<p>
When a using declaration names a base class constructor, a number of <em>forwarding
constructors</em> are implicitly declared in the derived class.  Like other implicitly
declared constructors, they are only implicitly defined if they are <em>used</em>.
<p>
Copy and default constructors are <b>not</b> forwarded, deferring to the existing rules
for implicitly declaring copy/default constructors.
<p>
As forwarding constructors are implicitly declared, they do not inhibit the implicit
declaration of the default constructor.
<p>
Forwarding constructors retain the throw spec and explicitness of the base constructor.
<p>
User declared constructors inhibit forwarding for that particular signature, much as
user declaration of a function would hide a specific signature when using declarations
are used with regular functions.
<p>
It is an error for multiple using declarations to refer to the same base class.  If
multiple using directives declare the same signature, the program is ill-formed, even
if those constructors are not used.  This can be worked around with a user-declared
constructor instead.
<p>
A program is ill-formed if a fowarding constructor is used
that forwards to a base
class constructor that is declared private.  Note that this is different to the
using declarations with regular functions, that are ill-formed even if the private
function is not used.  It is consistent with the way a variadic constructor template
would work though.
<p>
Typically, forwarding constructor definitions for classes with virtual bases will
be ill-formed, unless the virtual base supports default initialization, or the
virtual base is a direct base, and named as the base forwarded-to.  Likewise, all
data members and other direct bases must support default initialization, or any
attempt to use a forwarding constructor will be ill-formed.  Note: ill-formed when
used, not declared.
<p>
Note that typedef names that alias a direct base will work in the same way, and
it is even possible to mix and match names either side of the ::.<br>
For example:
<blockquote>
<pre>
<code>
struct derived : base {
  typedef base inherited;
};
</code>
</pre>
</blockquote>

The following would all be valid using declarations, and all mean the same thing.
Attempting to use any combination of more than of these would be ill-formed for
the same reason that multiple declarations of the same name are ill-formed.
<ul>
<li>using base::base;</li>
<li>using base::inherited;</li>
<li>using inherited::base;</li>
<li>using inherited::inherited;</li>
</ul>

<h2>Proposed Changes to the Working Paper</h2>

Changes in the wording from the previous paper:
<ul>
<li>handle constexpr
<li>properly forward rvalues
<li>handle name lookup
<li>does not address deleted constructors yet; needs update to 12.9 to
copy deletedness to derived class constructor similar to explicit and
constexpr
</ul>
<p>

Change 3.4.3.1 class.qual paragraph 2 as indicated:
<blockquote>

In a lookup in which the constructor is an acceptable lookup result,
if the <em>nested-name-specifier</em> nominates a class C,
<strike>and</strike>
<b>additional conditions apply to</b>
the name specified after the nested-name-specifier.

<b>If that name</b>, when looked up in C, is the
injected-class-name of C (clause 9), the name is instead considered to
name the constructor of class C.

[ Note: For example, the constructor
is not an acceptable lookup result in an
<em>elaborated-type-specifier</em> so the constructor would not be
used in place of the injected-class-name. ]

<b>Furthermore, if the <em>nested-name-specifier</em> appears in a
<em>using-declaration</em> and that name, when looked up in C,
nominates (possibly cv-qualified) class C, the name is instead considered to name the
constructor of class C.  If that lookup does not find the name, the
name is also looked up in the context of the entire
<em>using-declaration</em>.  If the name is found and nominates the
(possibly cv-qualified) class C, the name is instead considered to
name the constructor of class C.</b>

Such a constructor name shall be used only in the declarator-id of a
declaration that names a constructor <b>or in a
<em>using-declaration</em> that names a constructor.</b>
</blockquote>

Change 7.3.3 namespace.udecl paragraph 1 as follows
<blockquote>
A <em>using-declaration</em> introduces a name into the declarative region in
which the <em>using-declaration</em> appears. That name is a synonym
for the name of some entity declared elsewhere.
<p>
<pre>
<em>using-declaration:</em>
  using typename<sub><em>opt</em></sub> ::<sub><em>opt</em></sub> <em>nested-name-specifier unqualified-id</em> ;
  using :: <em>unqualified-id</em> ;
</pre>

<p>
The member name specified in a <em>using-declaration</em> is declared in the
declarative region in which the <em>using-declaration</em> appears. [Note:
only the specified name is so declared; specifying an enumeration name
in a <em>using-declaration</em> does not declare its enumerators in the
<em>using-declaration</em>'s declarative region. -- end note ]
<b>Moreover, if a <em>using-declaration</em> names a constructor
(3.4.3.1 class.qual), it implicitly declares a set of constructors in the
class in which the <em>using-declaration</em> appears (12.9
class.fwd).</b>
</blockquote>

Change 7.3.3 namespace.udecl paragraph 3 as follows
<blockquote>
In a <em>using-declaration</em> used as a <em>member-declaration</em>, the
<em>nested-name-specifier</em> shall name a base class of the class
being defined.  <b>If such a <em>using-declaration</em> names a
constructor, the <em>nested-name-specifier</em> shall name a direct
base class of the class being defined,
otherwise it</b> <strike>Such a <em>using-declaration</em></strike>
introduces the set of declarations found by member name lookup (10.2,
3.4.3.1).

</blockquote>

Change 7.3.3 namespace.udecl paragraph 4 as follows
<blockquote>
[ Note: <strike>since constructors and</strike> <b>Since</b> destructors do not
have names,</strike> a using-declaration cannot refer to <strike>a
constructor or </strike> a destructor for a base class. Since
specializations of member templates for conversion functions are not
found by name lookup, they are not considered when a using-declaration
specifies a conversion function (14.5.2). -- end note ] ...
</blockquote>

Change 7.3.3 namespace.udecl paragraph 14 as follows
<blockquote>
When a <em>using-declaration</em> brings names from a base class into a derived
class scope, 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),
and cv-qualification in a base class (rather than conflicting).
<b>[Note: For <em>using-declaration</em>s that name a constructor, see
12.9 class.fwd]</b>
</blockquote>


Change 7.3.3 namespace.udecl paragraph 17 as follows
<blockquote>
All instances of the name mentioned in a
<em>using-declaration</em> shall be accessible. In particular, if a
derived class uses a <em>using-declaration</em> to access a member of a base
class, the member name shall be accessible. If the
name is that of an overloaded member function, then all functions
named shall be accessible.  The base class members mentioned by a
<em>using-declaration</em> shall be visible in the scope of at least one of the
direct base classes of the class where the <em>using-declaration</em> is
specified.  <b>[Note: Since constructors do not have names, these
access rules do not apply to constructors, see 12.9 class.fwd]</b>
...
</blockquote>

Change 7.3.3 namespace.udecl paragraph 18 as follows
<blockquote>
The alias created by the <em>using-declaration</em> has the usual
accessibility for a <em>member-declaration</em>.  <b>A constructor
declared by a <em>using-declaration</em> has the accessibility as if
it were declared with the <em>access-specifier</em> that applied to
the corresponding constructor in the base class.</b>
</blockquote>


Create a new section 12.9 class.fwd [not shown in bold here]:
<blockquote> 12.9 Forwarding Constructors [class.fwd]
<p>
A <em>using-declaration</em> (7.3.3 namespace.udecl) that names a
constructor implicitly declares a set of <em>forwarding
constructors</em>.  For each non-template constructor other than a
default or copy
constructor in the class named in the <em>using-declaration</em>, a
constructor is implicitly declared with the same parameter-type-list
(8.3.5 dcl.fct), <em>exception-specification</em> (15.4 except.spec),
absence or presence of <code>explicit</code> (7.1.2 dcl.fct.spec), and
absence or presence of <code>constexpr</code> (7.1.6 dcl.constexpr),
unless there is a user-declared constructor with the same
signature in the class where the <em>using-declaration</em>
appears.  Similarly, for each constructor member function template in the class
named in the <em>using-declaration</em>, a constructor member function
template is implicitly declared with the same template parameter list
(14.1 temp.param), parameter-type-list (8.3.5 dcl.fct),
<em>exception-specification</em> (15.4 except.spec), absence or
presence of <code>explicit</code> (7.1.2 dcl.fct.spec), and
absence or presence of <code>constexpr</code> (7.1.6 dcl.constexpr)
unless there is an equivalent user-declared constructor member
function template
(14.5.5.1 temp.over.link)  in the class where the
<em>using-declaration</em> appears.

[<em>Note:</em> Default and copy constructors may be
implicitly declared as specified in 12.1 class.ctor and 12.8
class.copy.]
<p>
[<em>Note:</em> If two <em>using-dclarations</em> declare forwarding
constructors with the same signatures, the program is ill-formed (9.2
class.mem).
<p>
<pre>
<code>
struct B1 {
  B1( int );
};

struct B2 {
  B2( int );
};

struct D1 : B1, B2 {
  using B1::B1;
  using B2::B2;  // ill-formed implicitly declaring same ctor twice
};

struct D2 : B1, B2 {
  using B1::B1;
  using B2::B2;
  D2( int );  // user declaration prevents conflict
};
</code>
</pre>
 ]
<p>
An implicitly-declared forwarding constructor for a class is
implicitly defined when it is used (3.2 basic.def.odr) to create an
object of its class type (1.8 intro.object).  An implicitly-defined
forwarding constructor performs the set of initializations of the
class that would be performed by a user-written <code>inline</code>
constructor for that class with a <em>mem-initializer-list</em> whose
only <em>mem-initializer</em> has a <em>mem-initializer-id</em> that
names the base class named in the <em>using-declaration</em> and an
<em>expression-list</em> as specified below, and with an empty
function body (12.6.2 class.base.init).  If that user-written
constructor would be ill-formed, the program is ill-formed.  Each
<em>expression</em> in the <em>expression-list</em> is of the form
<code>static_cast&lt;<em>T</em>&amp;&amp;>(<em>p</em>)</code> where <code><em>p</em></code> is
the name of the corresponding constructor parameter and <code><em>T</em></code> is
the declared type of <code><em>p</em></code>.


<p>
[ Example:
<pre>
<code>
struct B1 {
  B1( int ) {}
};

struct B2 {
  B2( double ) {}
};

struct D1 : B1 {
  using B1::B1; // implicitly declares D1( int )
  int x;
};

D1 d(6);        // ok; d1.x is not initialized
D1 e;           // error: base class B1 has no default constructor

struct D2 : B2 {
  using B2::B2; // ok, implicitly declares D2( double )
  B1 b;
};

D2 f(1.0);      // error: use of D2( double ) is ill-formed

template< class T >
struct D : T {
  using T::T;   // declares all constructors from class T
  ~D() { clog << "Destroying wrapper" << endl; }
};
</code>
</pre>

Class template D wraps any class and forwards all its constructors,
while writing a message to the standard log whenever an object of
class D is destroyed.
<p>
]
</blockquote>


<p>
&nbsp;
<p>


While drafting the wording for this paper, it occurred to one of the
authors that the standard currently defines "default constructor" in
terms of whether a constructor can be called with no arguments.
Thus, for a class C, C(int x = 42) is a default constructor.  An
implicitly declared default constructor could have that signature,
which seems a bit surprising.  Unrelated to the proposed semantics in
this paper, we propose to change 12.1 class.ctor paragraph 5 as follows
<blockquote>
A <em>default constructor</em> 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 <strike>default</strike> constructor
<b>with no arguments</b> is implicitly declared. ...
</blockquote>


</body>
</html>

