10

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?

1 Answer 1

18

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.

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

5 Comments

uniform initialization syntax should be avoided for exactly these reasons ... and for many other reasons like changing semantics when modifying S.
@ipc: I would not go as far, but the fact is that it can be tricky at times :)
@zahir: Yes. Some of us would like to fix that, but there seems to be strong opposition to the very idea of uniform initialization, let alone to actually correcting the problem and making it uniform.
There exists a core issue for this, too.
@JohannesSchaub-litb do you know if it was resolved in C++14?

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.