Включить конструктор списка инициализаторов по умолчанию
Я полагаю, что современные списки инициализаторов C++ очень полезны для инициализации объектов, так что отпадает необходимость в определении собственного конструктора:
struct point
{
float coord[3];
};
point p = {1.f, 2.f, 3.f}; // nice !
Однако это не работает, когда мой класс наследуется от другого класса:
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 :(
Я пытался добавить point() = default;
к моему классу, но это тоже не сработало. Как я могу все еще инициализировать точку с помощью списка инициализаторов?
1 ответ
Ваш исходный случай основывался на общей инициализации [dcl.init.list]:
Инициализация списка объекта или ссылки типа T определяется следующим образом:
...
- В противном случае, еслиT
агрегат, выполняется агрегатная инициализация
Где агрегатная и агрегатная инициализация, из [dcl.init.aggr], акцентирует мое внимание:
Агрегат - это массив или класс (раздел 9) без предоставленных пользователем конструкторов (12.1), без закрытых или защищенных нестатических элементов данных (пункт 11), без базовых классов (пункт 10) и без виртуальных функций (10.3).
Когда агрегат инициализируется списком инициализаторов, как указано в 8.5.4, элементы списка инициализаторов берутся в качестве инициализаторов для элементов агрегата в порядке возрастания индекса или элемента. Каждый член инициализируется копией из соответствующего предложения инициализатора.
Но сейчас, так как point
имеет базовый класс (serializable<point>
), point
больше не является агрегатом и больше не поддерживает инициализацию агрегата.
Решение состоит в том, чтобы просто предоставить такой конструктор для инициализации point
:
struct point : public serializable<point>
{
template <typename... T>
point(T... ts)
: coord{ts...}
{ }
float coord[3];
};