Search code examples
c++c++11copy-constructorinitializer-listuniform-initialization

'Excess elements in struct initializer' error with C++11 uniform initialization


I am surprised by the following compiler error:

template <typename T>
struct A
{
    A(T t): t_{t} {}

    T t_;
};

struct S
{
};

int main()
{
    A<S> s{S{}};
}

The error is (with clang):

test.cpp:4:16: error: excess elements in struct initializer
    A(T t): t_{t} {}
               ^
test.cpp:15:10: note: in instantiation of member function 'A<S>::A' requested here
    A<S> s{S{}};
         ^

GCC gives a similar error.

I would expect the expression t_{t} to try to copy construct t_ from t. Since S has an implicitly generated copy constructor, I wouldn't expect this to be a problem.

Could someone explain what is going on here?


Solution

  • S may have an implicitly generated copy constructor, but S is also something else. An aggregate. Therefore, (almost) any use of {} will perform aggregate initialization on it. So the contents of {} are expected to be values for the members of the aggregate. And since your aggregate is empty... boom.

    In template code, uniform initialization syntax should be avoided for exactly these reasons. For an unknown type T, you can't be sure exactly what {...} will do.