Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 874
HighCommander4 Avatar asked Feb 20 '13 22:02

HighCommander4


People also ask

How to initialize struct members c++?

// In C++ We can Initialize the Variables with Declaration in Structure. Structure members can be initialized using curly braces '{}'.

How to initialize union in c++?

A union can have a constructor to initialize any of its members. A union without a constructor can be initialized with another union of the same type, with an expression of the type of the first member of the union, or with an initializer (enclosed in braces) of the type of the first member of the union.

How initialize struct?

When initializing a struct, the first initializer in the list initializes the first declared member (unless a designator is specified) (since C99), and all subsequent initializers without designators (since C99)initialize the struct members declared after the one initialized by the previous expression.


1 Answers

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.

like image 58
Nicol Bolas Avatar answered Sep 28 '22 04:09

Nicol Bolas