Question

I have the following code, a simplification of an array-like structure:

template<typename T, size_t N>
struct X
{
    T a[N];

    template<typename... A>
    explicit X(A&&... a) : a{std::forward<A>(a)...} { }  // ERROR (2)
};

int main ()
{
    X<int,3> x;           // OK
    X<X<int,3>,2> y{x,x}; // OK
    X<X<int,3>,2> z;      // ERROR (1)
}

This is compiling fine in clang 3.3 and gcc 4.8.1, both with -std=c++11. I am trying to upgrade gcc, so I now try 4.9.0. In this case, the 3rd example (ERROR (1)) instantiates X's constructor (ERROR (2)), at which point the compiler reports

error: converting to 'X<int, 3ul>' from initializer list would use explicit
   constructor 'X<T, N>::X(A&&...) [with A = {}; T = int; long unsigned int N = 3ul]

This last example attempts to default-initialize array z and so also its included arrays; however, if I get this right, here gcc essentially says that the included arrays are being list-initialized by {}, which is not allowed since the constructor is explicit.

The error is gone if I add another default constructor of either of the following forms:

explicit X() {}
explicit X() : a() {}

but not

explicit X() : a{} {}

This workaround is not difficult, but any idea who's wrong and who's right, just so I know what I'm doing and why?

Was it helpful?

Solution

This is a GCC bug, PR 60417.

An older change for PR 54835 was intended to implement the C++ committee's proposed direction for fixing core issue 1518. Unfortunately that change breaks some valid C++03 programs, as shown by the first example in PR 60417. A fix was committed for PR 60417, but it only handles some cases. Specifically, it doesn't fix the case where list-initializing an array of types with explicit constructors, as in this question.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top