7

Я считаю, что современным 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; к моей точке класса, но это не сработало. Как я могу инициализировать точку с помощью списка инициализаторов?

ответ

8

Ваш оригинальный корпус опирался на агрегированном инициализации [dcl.init.list]:

Список инициализация объекта или ссылки типа T определяется следующим образом:
...
- В противном случае , если T представляет собой агрегат, совокупная инициализация выполняется

Где совокупность и совокупного initialiazation являются, с [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]; 
}; 
+0

благодарственным для вас четкого и подробного ответа. Это оправдывает меня, почему стандарт такой. Я предполагаю, что это потому, что конструктор s иначе не будет называться ... и, возможно, в некоторых случаях они могут быть связаны между конструкторами и инициализацией списка. Однако, поскольку все конструкторы являются '= default', которые не должны вызывать никаких проблем – Amxx

+0

@Amxx Что делать, если базовые классы имели членов? Что делать, если эти члены по умолчанию являются конструктивными? Непонятно, что «правильная вещь» делать во всех этих случаях - поэтому стандарт предпочитает не догадываться. – Barry

+0

Вы также можете наполнить свои данные членом или базовым классом, например 'struct point_data {float coord [3]; } ', тогда есть« идеальный конструктор переадресации », который создает' {} 'основанную на нем конструкцию. – Yakk