Per § 12.2.2.1 [over.match.funcs.general]/9-sentence-2:
A constructor inherited from class type C ([class.inhctor.init]) that has a first parameter of type “reference to cv1 P” (including such a constructor instantiated from a template) is excluded from the set of candidate functions when constructing an object of type cv2 D if the argument list has exactly one argument and C is reference-related to P and P is reference-related to D.
I am just trying to understand this paragraph and somehow conduct an example that matches the wording then I want to apply that example to the paragraph:
struct P;
struct C { C(); C(const P&); };
struct P : C { using C::C; };
struct D : P {};
D d{ P() }; // OK: calls compiler-generated D::D(const P&); C::C(const P&) is not a candidate.
From the above example: C
is reference-related to P
and P
is reference-related to D
. And there's a constructor inherited from class type C
that has a first parameter of type “reference to cv1 P
”. And when constructing an object of type cv D
-and the argument list has exactly one argument which is P()
- then this inherited constructor is excluded from the set of candidate functions.
Does my example match what the wording intends? And Do I understand and parse the wording correctly? Also, Is there any other wording regarding this point (inheriting copy/move constructors)?
CodePudding user response:
Does my example match what the wording intends? And Do I understand and parse the wording correctly?
Yes, and yes. The standard wording is, as many times, not the most human-reader-friendly, but the core working group issue that introduced the text, CWG 2356 summarizes in an easier-to-read form, which is in the same way as the OP has interpreted it:
2356. Base class copy and move constructors should not be inherited
[...]
Base class copy and move constructors brought into a derived class via a using-declaration should not be considered by overload resolution when constructing a derived class object.
Proposed resolution, February, 2018:
Change 16.3.1 [over.match.funcs] paragraph 8 as follows: [...]
CWG 2356 was accepted as a defect report and applies also for C 17.
Also, Is there any other wording regarding this point (inheriting copy/move constructors)?
C 17 implemented P0136R1 which did a re-work of the rules of inheriting constructors (hence the reason CWG 2356 was marked as a DR for C 17). I you want to dwell into the details, you may particularly read up on the core issues fixed by P0136R1:
- Core Issue 1573: Inherited constructor characteristics
- Core Issue 1645: Identical inheriting constructors via default arguments
- Core Issue 1715: Access and inherited constructor templates
- Core Issue 1736: Inheriting constructor templates in a local class
- Core Issue 1903: What declarations are introduced by a non-member using-declaration?
- Core Issue 1941: SFINAE and inherited constructor default arguments
- Core Issue 1959: Inadvertently inherited copy constructor
- Core Issue 1991: Inheriting constructors vs default arguments
CodePudding user response:
This example has nothing to do with inheriting constructors: it works even with either or both of C(const P&);
and using C::C;
removed. It’s doing aggregate initialization of a D
by supplying a value for its one subobject (the base P
). (In C 17, changing to D d((P()));
fails, but C 20 lets that be aggregate initialization too.)