1

This is a follow up question to Is this reference-initialization or aggregate-initialization?

Consider the same example:

struct A {};
struct B : A{};

A a{ B() };

Does this is an aggregate initialization or reference initialization?

I mean by "reference-initialization" that the implicity-declared copy constructor A::A(const A&) is used where the reference parameter is bound to A subobject of the initializer expression B().

Also why this is not an aggregate initialization even though the class A is an aggregate class?

mada
  • 1,646
  • 1
  • 15
  • This is not aggregate initialization because to do aggregate initialization bullet 3 [here](https://en.cppreference.com/w/cpp/language/list_initialization#Explanation) should be reached and satisfied but we never reach bullet 3 because bullet 1 is satisfied. – Jason Aug 25 '22 at 18:57
  • It is not aggregate initialization, because aggregate initialization wouldn't work. `A` has no base classes or members, so couldn't accept an argument for aggregate initialization. That's why they added rules that this form performs direct-initialization even if `A` is aggregate, see [CWG issue 1467](https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1467). That's better than simply having a stiff rule that `{/*...*/}` for an aggregate means aggregate-initialization with the result that this doesn't compile at all although it has a clear intended behavior. – user17732522 Aug 25 '22 at 19:14

1 Answers1

2

Does this is an aggregate initialization or reference initialization?

A is an aggregate and A a{ B() } is list initialization according to the following rule(s):

The effects of list-list-initialization of an object of type T are:

  • If T is an aggregate class and the braced-init-list has a single element of the same or derived type (possibly cv-qualified), the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization).

  • Otherwise, if T is a character array and the braced-init-list has a single element that is an appropriately-typed string literal, the array is initialized from the string literal as usual.

  • Otherwise, if T is an aggregate type, aggregate initialization is performed.

(emphasis mine)

Note in the above, we do not reach bullet 3 as bullet 1 is satisfied and so used.

This means that the object A is initialized from the single element B() using direct-initialization. This in turn means that the copy constructor A::A(const A&) will be used.

Here, the parameter const A& of the copy ctor A::A(const A&) can be bound to a B object so this works without any problem.


why this is not an aggregate initialization even though the class A is an aggregate class?

Because to do aggregate initialization bullet 3 here should be reached and satisfied but we never reach bullet 3 because bullet 1 is satisfied.

Jason
  • 36,170
  • 5
  • 26
  • 60
  • I wonder what is the go-to guide on how one can decide which of the dozens C++ initialisations is used in an arbitrary case. Do you just go from top to bottom of [cppreference](https://en.cppreference.com/w/cpp/language/initialization) until it gives you best context, or you use more sophisticated approach? – The Dreams Wind Aug 25 '22 at 18:58
  • 1
    @TheDreamsWind I usually start with [cppreference](https://en.cppreference.com/w/cpp/language/initialization) and then to confirm that i've understood everything correctly i read the same topic in the standard. This way seems to work for me. – Jason Aug 25 '22 at 19:00
  • @TheDreamsWind [Some good viewing](https://www.youtube.com/watch?v=7DTlWPgX6zs). It's about an hour long, but worth it. – user4581301 Aug 25 '22 at 19:44