I believe modern C++ initializer lists are very useful for initializing objects, to the point of removing the need for defining your own constructor:
struct point
{
float coord[3];
};
point p = {1.f, 2.f, 3.f}; // nice !
However, this doesn't work when my class inherits from another class:
template<typename T>
class serializable
{
protected:
serializable() = default;
...
// other stuff
}
struct point : public serializable<point>
{
float coord[3];
};
point p = {1.f, 2.f, 3.f}; // Doesn't work :(
I tried adding point() = default;
to my point class, but that didn't work either. How can I still initialize point with an initializer list?
Your original case relied upon aggregate initialization [dcl.init.list]:
List-initialization of an object or reference of type T is defined as follows:
...
— Otherwise, ifT
is an aggregate, aggregate initialization is performed
Where an aggregate and aggregate initialiazation are, from [dcl.init.aggr], emphasis mine:
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
When an aggregate is initialized by an initializer list, as specified in 8.5.4, the elements of the initializer list are taken as initializers for the members of the aggregate, in increasing subscript or member order. Each member is copy-initialized from the corresponding initializer-clause.
But now, since point
has a base class (serializable<point>
), point
is no longer an aggregate and no longer supports aggregate initialization.
The solution is to simply provide such a constructor to initialize point
:
struct point : public serializable<point>
{
template <typename... T>
point(T... ts)
: coord{ts...}
{ }
float coord[3];
};
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