3

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?

16
  • 1
    The simplest fix is to add X() : a{} {} (without the explicit). I think this is related to gcc.gnu.org/PR60416 and open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1518 Commented Mar 27, 2014 at 19:38
  • 1
    I think this is a GCC 4.9 regression, which I've reported to bugzilla, but as issue 1518 shows, the standard isn't really clear what should happen. Commented Mar 27, 2014 at 19:49
  • @JonathanWakely The real simplest fix is to use std::array and get the same functionality without reinventing the wheel :-P Commented Mar 27, 2014 at 19:54
  • @MadScienceDreams No. using std::array<T,N> a; instead of T a[N]; does not change anything. The problem remains. Commented Mar 27, 2014 at 20:49
  • 1
    Follow the link from PR60416 to gcc.gnu.org/PR60417 and you'll see the original testcase was fixed, but I've added an new testcase as a comment. It's the same issue. Commented Mar 27, 2014 at 22:09

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.