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?
// In C++ We can Initialize the Variables with Declaration in Structure. Structure members can be initialized using curly braces '{}'.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With