c++compiler-errorsaggregate-initialization

Erroneous example for aggregate intializaton?


The following example has been provided for aggregate initialization under Direct Initialization

struct A
{
    explicit A(int i = 0) {}
};
 
A a[2](A(1)); // OK: initializes a[0] with A(1) and a[1] with A()
A b[2]{A(1)}; // error: implicit copy-list-initialization of b[1]
              //        from {} selected explicit constructor

The above code which has been OKed in the example doesn't compile for me:

main.cpp: In function ‘int main()’:
main.cpp:8:14: error: converting to ‘A’ from initializer list would use explicit constructor ‘A::A(int)’
    8 |   A a[2](A(1));
      |              ^
compilation terminated due to -Wfatal-errors.

The following is my complete source code based on the above example:

struct A
{
  explicit A(int i = 0){}
};

int main (){

  A a[2](A(1));
  A b[2]{A(1)};

  return 0;
}

The compilation command I am using is as shown below (compiler version is gcc 11.3.1):

g++ -ggdb -g3 -pedantic-errors -Wall -Wextra -Wfatal-errors -Wpedantic -std=c++20

Thoughts?

TIA


Solution

  • cppreference is correct, and GCC is wrong here. (But Clang gets it right. See Godbolt.) This initialization is governed by [dcl.init.general]/16.5:

    Otherwise, if the destination type is an array, the object is initialized as follows. Let x1, …, xk be the elements of the expression-list. If the destination type is an array of unknown bound, it is defined as having k elements. Let n denote the array size after this potential adjustment. If k is greater than n, the program is ill-formed. Otherwise, the ith array element is copy-initialized with xi for each 1 ≤ i ≤ k, and value-initialized for each k < in. For each 1 ≤ i < j ≤ n, every value computation and side effect associated with the initialization of the ith element of the array is sequenced before those associated with the initialization of the jth element.

    There is no obstruction to value-initializing an object that has an explicit default constructor, except, as specified by [over.match.ctor]/1, when the initialization is "in the context of copy-initialization", which is not the case here, since the direct-initialization syntax was used.

    However, when you use aggregate initialization syntax, then any elements that don't have a specified initializer are copy-initialized from {}, so an explicit default constructor is not permitted to be selected in this context.