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

1

6

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?

Seadon answered 3/5, 2022 at 16:25 Comment(4)
I don't understand the question. You mention "aggregate initialization", which suggests that you've already figured out no constructor is getting called in D, but then you talk about copy constructors as though one is. The answer is that it's aggregate initialization.Seamaid
Does this answer your question? Aggregate initialization of a derived classUniverse
Not sure if this is the best duplicate, but it's just an aggregate initialization. The first parameter of the initialization initializes the parent.Universe
@SilvioMayolo "You mention "aggregate initialization", which suggests that you've already figured out no constructor is getting called in D" That's already what I am conflating, That's why I ask.Seadon
A
5

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.

Allemande answered 3/5, 2022 at 16:30 Comment(6)
So this means in this initialization D d{ B() }; no copy constructor is required? So the compiler does not generates copy constructors; the subobject of B() is direct-intialized to d. Right? I mean no copying/moving happensSeadon
@SofaJoe So the compiler does not generates copy constructors The copy constructors are trivial in this case, so there is nothing for compiler to generate. The trivial copy constructors are concepts for the abstract machine for purposes of language rules.Allemande
Literally thanks but just to ensure. when "aggregate initialization" is performed, no copy/move constructor is called, instead, the aggregate is direct-initialized from the baced-init-list. Right?Seadon
@SofaJoe No constructor of the enclosing class is called. The sub objects of the aggregate are initialised directly. That may or might not involve calling copy/move constructor of the sub object depending on the case.Allemande
"The sub-objects of the aggregate are initialized directly." Do you mean the aggregate itself is direct initialized from the corresponding clause of the initializer list?Seadon
@SofaJoe The aggregate is aggregate initialised.Allemande

© 2022 - 2024 — McMap. All rights reserved.