When I run this code:
struct X {
int a;
};
struct Y : public X {};
X x = {0};
Y Y = {0};
I get:
error: could not convert ‘{0}’ from ‘<brace-enclosed initializer list>’ to ‘Y’
Why does brace initialization work for the base class but not the derived class?
Your problem has to do with aggregate initialization:
struct X
is an aggregate whilestruct Y
is not. Here is the standard quote about aggregates (8.5.1):This clause specifies that if a
class
has a base class, then it's not an aggregate. Here,struct Y
hasstruct X
as a base class and thus cannot be an aggregate type.Concerning the particular problem you have, take the following clause from the standard:
When you do
X x = {0}
, aggregate initialization is used to initializea
to0
. However, when you doY y = {0}
, sincestruct Y
is not an aggregate type, the compiler will look for an appropriate constructor. Since none of the implicitely generated constructors (default, copy and move) can do anything with a single integer, the compiler rejects your code.Concerning this constructors lookup, the error messages from clang++ are a little bit more explicit about what the compiler is actually trying to do (online example):
Note that there is a proposal to extend aggregate initialization to support your use case, and it made it into C++17. If I read it correctly, it makes your example valid with the semantics you expect. So... you only have to wait for a C++17-compliant compiler.