This is a GCC bug.
The default constructor of B
uses aggregate initialization to initialize a
with no initializers. [dcl.init.aggr]/8:
If there are fewer initializer-clauses in the list than there are
elements in a non-union aggregate, then each element not explicitly
initialized is initialized as follows:
If the element has a default member initializer ([class.mem]), the element is initialized from that initializer.
Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list ([dcl.init.list]).
Otherwise, the program is ill-formed.
[...]
So a[0]
is copy-initialized from {}
, which is copy-list-initialization. This is probably where GCC starts to get confused — copy-initialization does not necessarily involve the copy constructor.
[dcl.init.list]/3.4:
List-initialization of an object or reference of type T
is defined as
follows:
Therefore, the default constructor of A
is used directly. There's no copy constructor involved. Nor triviality.
In case you are worrying about the difference between C++11 and C++17, N3337 [dcl.init.aggr]/7:
If there are fewer initializer-clauses in the list than there are
members in the aggregate, then each member not explicitly initialized
shall be initialized from an empty initializer list ([dcl.init.list]).
[...]
Copy-initialization isn't even involved here. And N3337 [dcl.init.list]/3.1:
List-initialization of an object or reference of type T
is defined
as follows:
No change.