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?
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.