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

Time:05-04

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:

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?

CodePudding user response:

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.

  • Related