This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
(See also submission #545.)
Consider:
struct A { int n; }; struct B : A { using A::A; B(int); };
Does B have a default constructor?
Suggested resolution [SUPERSEDED]:
Change in 9.9 [namespace.udecl] paragraph 4 as follows:
If a constructor or assignment operator brought from a base class into a derived class has the signature of a default constructor or copy/move constructor or assignment operator for the derived class (11.4.5.2 [class.default.ctor], 11.4.5.3 [class.copy.ctor], 11.4.6 [class.copy.assign]), the using-declaration does not by itself suppress the implicit declaration of the derived class member; the member from the base class is hidden or overridden by the implicitly-declaredcopy/move constructor or assignment operatorspecial member function of the derived class, as described below.
Change in 11.4.5.2 [class.default.ctor] paragraph 1 as follows:
A default constructor for a class X is a constructor of class X for which each parameter that is not a function parameter pack has a default argument (including the case of a constructor with no parameters). If there is no user-declared constructor for class X, or if X inherits (9.9 [namespace.udecl]) one or more default constructors and there is no user-declared default constructor for X, a non-explicit constructor having no parameters is implicitly declared as defaulted (9.5 [dcl.fct.def]). An implicitly-declared default constructor is an inline public member of its class.
Proposed resolution [SUPERSEDED]:
(This also resolves issue 2632.)
Change in 9.9 [namespace.udecl] paragraph 4 as follows:
If a constructor or assignment operator brought from a base class into a derived class has the signature of a copy/move constructor or assignment operator for the derived class (11.4.5.3 [class.copy.ctor], 11.4.6 [class.copy.assign]), the using-declaration does not by itself suppress the implicit declaration of the derived class member; the member from the base class is hidden or overridden by the implicitly-declared copy/move constructor or assignment operator of the derived class, as described below.[ Note: A using-declarator that names a member function of a base class does not suppress the implicit declaration of a special member function in the derived class, even if their signatures are the same (11.4.5.2 [class.default.ctor], 11.4.5.3 [class.copy.ctor], 11.4.6 [class.copy.assign]). -- end note ]
Add a new paragraph before 11.4.1 [class.mem.general] paragraph 2 as follows:
... For any other member-declaration, each declared entity that is not an unnamed bit-field (11.4.10 [class.bit]) is a member of the class, termed a user-declared member, and each such member-declaration shall either declare at least one member name of the class or declare at least one unnamed bit-field.
Change in 11.4.5.2 [class.default.ctor] paragraph 1 as follows:
A default constructor for a class X is a constructor of class X for which each parameter that is not a function parameter pack has a default argument (including the case of a constructor with no parameters). Ifthere is noa class X does not have a user-declared constructorfor class X, or if X inherits (9.9 [namespace.udecl]) one or more default constructors and X does not have a user-declared default constructor, a non-explicit constructor having no parameters is implicitly declared as defaulted (9.5 [dcl.fct.def]). An implicitly-declared default constructor is an inline public member of its class. [ Example:struct A {}; struct B {}; struct C : A, B { using A::A, B::B; C(int); }; C c; // OK struct X { X(int = 0, int = 0); }; // #1 struct Y { Y(int = 0); }; // #2 struct Z : X, Y { using X::X, Y::Y; }; Z z2(1, 1); // OK, invokes X(1, 1) and Y() Z z1(1); // error: ambiguous between #1 and #2 Z z0; // OK, invokes X() and Y()-- end example ]
Change in 11.4.5.3 [class.copy.ctor] paragraph 6 as follows:
If the classdefinitiondoes notexplicitly declarehave a user-declared copy constructor, a non-explicit one is declared implicitly. ...
Change in 11.4.5.3 [class.copy.ctor] paragraph 8 as follows:
Ifthe definition ofa class X does notexplicitly declarehave a user-declared move constructor, a non-explicit one will be implicitly declared as defaulted if and only if ...
Add a new paragraph before 11.4.5.3 [class.copy.ctor] paragraph 11 as follows:
[ Note: A using-declaration in a derived class C that names a constructor from a base class never suppresses the implicit declaration of a copy/move constructor of C, even if the base class constructor would be a copy or move constructor if declared as a member of C. -- end note]
A copy/move constructor for class X is trivial if it is not user-provided and if: ...
Change in 11.4.6 [class.copy.assign] paragraph 2 as follows:
If the classdefinitiondoes notexplicitly declarehave a user-declared copy assignment operator, one is declared implicitly. If the classdefinition declareshas a user-declared move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted; otherwise, it is defaulted (9.5 [dcl.fct.def]). The latter case is deprecated if the class has a user-declared copy constructor or a user-declared destructor (D.7 [depr.impldec]). ...
Additional notes (November, 2023)
How does access checking interact with the proposed resolution above?
struct B { protected: B(int = 0); }; struct A : B { using B::B; A(void *); }; A a; // okay? A aa(42); // not okay
CWG 2023-11-06
CWG resolved not to declare a default constructor in the derived class, but instead apply the usual rules for inherited constructors for this case. The wording should be changed so that the presence of a default constructor is never checked, in particular for "trivial class" (11.2 [class.prop], fixed by P3247R1 (Deprecate the notion of trivial types)), vacuous initialization (6.7.3 [basic.life] paragraph 1, fixed by issue 2859), and value initialization (9.4.1 [dcl.init.general] paragraph 9, also fixed by issue 2859).