Кажется, если вы немного сократите периоды разбрызгивания повсюду, у вас должно быть все в порядке!Пакеты параметров не являются чем-то особенным: они просто развернуты в отдельный список запятых.То есть, если вы измените свой код, чтобы он стал таким, как показано ниже, у вас должно быть все в порядке:
template <typename... Bases>
struct CompositeClass: public Bases... {
template <typename... Arguments>
CompositeClass(Arguments&&... arguments):
Bases(std::forward<Arguments>(arguments))...
{}
};
За исключением добавления двоеточия перед списком инициализатора, я удалил только некоторые лишние "...".Это работает нормально до тех пор, пока все ваши аргументы шаблона на самом деле являются типами классов и если они оказываются разными.Очевидно, что типы, которые не являются классами, не могут использоваться в качестве баз.Если вам нужен один и тот же тип несколько раз как базовый, вам нужно косвенно наследовать их, почему вспомогательный тип, который дает им число.Генерация чисел немного сложна в первые несколько раз, когда вы делаете это, но на самом деле тоже ничего волшебного.
Расширение отредактированного вопроса: Вы хотите передать списки аргументов каждому отдельному конструктору базового класса?Если можно передать std:tuple<...>
в качестве аргументов вашему CompositeClass
, это тоже выполнимо.По сути, вам нужно преобразовать каждый std::tuple<...>
в список аргументов.Это также требует генерации указанных индексов.Я бы, по крайней мере, начал со вспомогательной базы, которая принимает std::tuple<...>
в качестве аргумента и передает членов в качестве аргументов в базу.Это будет использовать что-то похожее на код выше для CompositeClass
, а основной трюк будет во вспомогательном классе:
template <int... Numbers> struct Sequence {};
template <int N> struct MakeSequence;
template <typename Base>
struct AuxiliaryBase: Base {
template <typename Tuple, int... Numbers>
AuxiliaryBase(Tuple&&, Sequence<Numbers...> const&);
};
template <typename... Bases>
struct CompositeClass: public AuxiliaryBase<Bases>... {
template <typename... Args>
CompositeClass(Args&&... arguments):
AuxiliaryBase<Bases>(std::forward<Args>(arguments),
typename MakeSequence<std::tuple_size<Args>::size>())...
{}
};
Реализация конструктора AuxiliaryBase
по существу требует наличия средства для созданияпоследовательность целых чисел от 0
до std::tuple_size<Tuple>::value
.Это займет немного настройки, но, безусловно, выполнимо.Чтобы сделать их доступными, передается вспомогательный параметр (я не уверен, что этого можно избежать; ну, возможно, его можно упаковать как тип с std::tuple<...>
, если этого следует избегать).При этом конструктор базового класса довольно прост:
template <typename Base>
template <typename Tuple, int... Numbers>
AuxiliaryBase<Base>::AuxiliaryBase(Tuple&& tuple, Sequence<Numbers...> const&):
Base(std::get<Numbers>(tuple)...)
{}
Я не проверял его, но что-то в этом роде должно действительно работать.Чего эта версия не делает, так это идеальной пересылки членов в std::tuple<...>
: для этого вам понадобится вариант std::forward<>()
, который принимает три аргумента, которые используют ссылочные квалификации внешнего типа, чтобы определить, какой тип ссылочных потребностейбыть вперед для члена.Я не пробовал это, но это, вероятно, тоже интересное упражнение.
Я не пытался скомпилировать этот конкретный пример, но я определенно делал что-то подобное в прошлом: если вы посмотрите слайды для презентации, которую я дал на конференции ACCU в 2010 , вы найдете все подробности о том, как это сделать (включая создание последовательности целых чисел;очень мало этого, на самом деле).