15

Consider the following contrived example

struct A {
    A(int) {}
    A(const A&) = delete;
    ~A() {}
};

struct B {
    A a[2] = {{1}, {2}};
};

int main() {
    B b;
}

It compiles fine in clang (any version) but not in GCC (any version, any standard >= C++11)

<source>: In constructor 'constexpr B::B()':
<source>:7:8: error: use of deleted function 'A::A(const A&)'
 struct B {
        ^
<source>:3:5: note: declared here
     A(const A&) = delete;
     ^
<source>: In function 'int main()':
<source>:12:7: note: synthesized method 'constexpr B::B()' first required here
     B b;
       ^

LIVE DEMO

When A's destructor is commented out, it compiles fine also in GCC.

Question is - who is right, clang or GCC, and why?

Initially I thought GCC is wrong, but then I saw [dcl.init.list]/5 which states that temporaries are created. Though I'm not sure if that applies here or if there's another rule that overrides this.

rustyx
  • 80,671
  • 25
  • 200
  • 267

1 Answers1

3

Since an array is an aggregate and aggregate initialization comes down to copy-initialization of aggregate members from the corresponding initializer-clauses, the question basically is: does copy-list-initialization (of array elements a[0] and a[1] from {1} and {2}, respectively) require copy constructor, but such question has already been answered — it does not.

BTW, GCC accepts A a = {1};, i.e. it has no problem with "direct" copy-list-initialization, but does not treat it correctly when members of aggregates are initialized.

Language Lawyer
  • 3,378
  • 1
  • 12
  • 29