Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritance of copy constructors in C++17

Consider the following example:

struct Parent
{
    Parent ();

    Parent (const Parent &);
};

struct Child : public Parent
{
    using Parent::Parent;
};

Parent p;

Child c (p);

This was taken from the following question: Why "an inherited constructor is not a candidate for initialization from an expression of the same or derived type"?

That original question asked about C++11. In C++11, there is wording that prevents Child from acquiring a constructor that takes const Parent&:

For each non-template constructor in the candidate set of inherited constructors other than a constructor having no parameters or a copy/move constructor having a single parameter, a constructor is implicitly declared with the same constructor characteristics unless there is a user-declared constructor with the same signature in the class where the using-declaration appears.

N4429 significantly changed the specification of inheriting constructors and was considered retroactive to C++11 (I think?). The purpose of N4429 was to cause the base class constructors to be visible as if they were derived class constructors, rather than declaring derived class constructors that delegate to base class constructors. In the first version of N4429, there is the following wording, keeping the restriction from C++11:

When a using-declaration declares that a class inherits constructors from a base class, the default constructor, copy constructor, and move constructor (if any) of the base class are excluded from the set of introduced declarations.

However, in the updated version of this paper, P0136R0, this wording is no longer present, and no explanation is given as to why. The paper was revised once more and then merged into the standard. So in C++17, I cannot see any rule that would prevent the above code from compiling.

Nonetheless, GCC and Clang both reject it. Clang says:

an inherited constructor is not a candidate for initialization from an expression of the same or derived type

However, I cannot find anything in the standard that says anything like this.

Is this code ill-formed in C++17? And if so, why?

like image 622
Brian Bi Avatar asked Sep 13 '19 15:09

Brian Bi


People also ask

Can copy constructor be inherited?

Copy constructor is not inherited.

Are constructors inherited in C?

This is all or nothing - you cannot inherit only some constructors, if you write this, you inherit all of them. To inherit only selected ones you need to write the individual constructors manually and call the base constructor as needed from them. Historically constructors could not be inherited in the C++03 standard.

What is copy constructor in C?

A copy constructor is a member function that initializes an object using another object of the same class. In simple terms, a constructor which creates an object by initializing it with an object of the same class, which has been created previously is known as a copy constructor.

How many copy constructors is a class allowed to have?

Hence, there is always one copy constructor that is either defined by the user or by the system.


1 Answers

[over.match.funcs]/8:

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.

See CWG2356.

like image 120
T.C. Avatar answered Oct 06 '22 23:10

T.C.