2015-03-17 3 views
1

У меня есть struct B, который получен из struct A.Инициализация объекта производного класса с использованием списка инициализаторов

struct A{ 
    int a; 
}; 

struct B : public A{ 
    int b; 
}; 

Есть прямой путь, чтобы инициализировать объект типа B без предоставления конструктора, скажем, с помощью инициализатора-лист?

Некоторые более глубокое:

я получил два struct сек, что я использую для передачи данных между потоками; второй содержит те же данные, что и первый, с добавлением некоторой переменной синхронизации . Я мог бы сделать первый struct членом данных второго или просто дублировать объявление элементов данных во втором struct, чтобы легко использовать список инициализаторов; но я думаю, что в этом конкретном приложении было бы логически более правильным, чтобы второй struct расширил первый.

ответ

3

существует не очень краткое решения, но является решением, по крайней мере:

#include <type_traits> 
#include <utility> 

struct B : A 
{ 
    int b; 

    template <typename ...Args, 
       typename = typename std::enable_if< 
          std::is_constructible<A, Args&&...>::value> 
    B(int x, Args &&... args) 
    : b(x), A(std::forward<Args>(args)...) 
    { } 
}; 

Это решение не совсем короткое, но оно общее. Новый конструктор для B существует только в тех специализациях, которые имеют смысл, благодаря возможности enable-if SFINAE, поэтому B точно так же конструктивна, как может быть.

Здесь еще одна опасность, о которой я не обращал, а именно о том, как должен быть новый конструктор explicit. В идеале он должен быть столь же явным, как и соответствующий конструктор A, но это немного сложно определить программно (как сделано в N4064 для пар и кортежей).

0

Вы не можете использовать агрегатную инициализацию для B, потому что это не совокупность, согласно [dcl.init.aggr]/1:

агрегат представляет собой массив или класс (пункт 9) без конструкторов, предоставляемых пользователем (12.1), без частных или защищенных нестатических данных (раздел 11), нет базовых классов (раздел 10) и виртуальных функций (10.3).

Update: Kerrek SB обеспечивается хорошее решение с использованием шаблона конструктора, но если вы хотите, вы можете добавить довольно простой конструктор без шаблона для B:

struct B : public A{ 
    int b; 
    B(const A& a_, int b_) : A(a_), b(b_) {} 
}; 

и использовать его с одной дополнительной парой Ортезы:

B b {{3}, 5};