Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can the compiler generates a default copy constructor that takes reference to different class type?

I have this example

struct B { B(); };
struct D : B { };
D d{ B() }; // what happens here? or why it's well-formed

This is an aggregate initialization, but I can’t understand how d is constructed? Does the compiler generates implicitly a copy constructor with this signature D::D(const D&) or D::D(const B&) or what? It’s clear that the compiler does not generate D::D(const D&) because const D& = B() is ill-formed. So this means it generates a copy constructor D::D(const B&)?

Now what would happen if I inherits constructors from B:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

struct B { B(); };
struct D : B { using B::B; };
D d{ B() }; // why it's ill-formed?

One said to me that the default copy constructor of B which is B::B(const B&) is inherited into D but it’s excluded from the set of candidates, that’s why it’s ill-formed. Is that true?

>Solution :

Can the compiler generates a default copy constructor that takes reference to different class type?

By definition, no. A constructor that accepts an object of another type is not a copy constructor. It would be a converting constructor.

No such converting constructor is implicitly generated.

This is an aggregate initialization, but I can’t understand how d is constructed?

No constructor of the enclosing class is called in aggregate initialisation. The sub objects are initialised directly.

D is an aggregate with a base class of type B. Aggregate initialisation is used to initialise this base sub object.

It’s clear that the compiler does not generate D::D(const D&) because const D& = B() is ill-formed.

Former cannot be deduced from the latter. In fact, there is a (trivial) D::D(const D&) which you can prove by attempting copy initialisation:

D d1{};
D d2(d1); // works

That said, a trivial constructor is a concept for the abstract machine, and the compiler doesn’t have to generate anything in practice.


Now what would happen if I inherits constructors from B

struct D : B { using B::B; };
D d{ B() }; // why it's ill-formed?

Having inherited constructors disqualifies the class from being an aggregate and hence aggregate initialisation does not apply. List initialisation will attempt to call a constructor, but no converting constructor exists.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading