2014-02-26 6 views
2

Я пытаюсь передать ряд параметров для двух различных классов подмешать следующим образом:Переходя кортеж к VARIADIC подмешать класс

template <typename... Checkers> 
class Checker : public Checkers... { 
public: 
    template<typename... Args> 
    Checker(Args&&... args) : Checkers(std::forward<Args>(args))... { } 
}; 

template <typename... Handlers> 
class Handler : public Handlers... { 
public: 
    template <typename... Args> 
    Handler(Args&&... args) : Handlers(std::forward<Args>(args))... { } 
}; 

template <typename C, typename H> 
class Tester : public C, H { 
public: 
    template <typename... ArgC, typename... ArgH> 
    Tester(std::tuple<ArgC...>&& argc, ArgH&&... argh) : C(argc), H(argh...) { 
    } 
}; 

Checker и Handler две разные коллекции подмешать классов с различными требованиями к каждый, но общие требования для всех участников. Я понимаю, что я не могу выполнять двойную вариационную конструкцию в Tester (компилятор не может определить, где разделить аргументы, передавая их всем обработчику и никому в Checker), поэтому я передаю аргументы Checker в аргументах Tuple и Handler в вариационный список. Проблема заключается в том, что конструктор Checker отвечает за пересылку этих параметров на свои базы. Обработчик может это сделать, потому что конструктор Handler является вариационным списком, но Checker получает кортеж, но вы не можете для каждого пересылать элементы кортежа, например forward, в список переменных параметров.

Любые советы были бы весьма полезными. Благодарю.

Дополнительное

Раствор должен был бы либо а) распаковать argc в Checker «с переменным числом конструктора или б) Сделать Checker» конструктору принять кортеж, а затем каким-то образом вперед каждый элемент этого кортежа к каждому из Checker Основание смеси, Checkers.... Я понимаю, что std::pair имеет трюк для пересылки кортежа в виде списка фиксированных аргументов в его типы, например 3-параметризованный конструктор std::vector с использованием маркера типа std::piecewise_construct, чтобы сообщить ему о распаковке, но я не вижу, как это может быть применяется здесь. Я посмотрел на реализацию GCC 4.8.1 std::pair с std::piecewise_construct и не мог понять это. Я прочитал некоторые из старых, pre-C++ 11 книг по метапрограммированию шаблонов (Современный дизайн C++ и C++ Template Metaprogramming, например), но я сейчас здесь не понимаю, что есть стандарт, и я пытаясь избежать Boost и Loki.

Дополнительная

должны соответствовать по крайней мере GCC 4.7.2. Решение, которое я нашел на основе std::pair, требует Наследование конструктора, которое не доступно до GCC 4.8.1, который не поддерживается моей системой сборки.

Дополнительная

Хотя GCC 4.6.3 поддержки было бы хорошо, Делегированные Конструкторы в 4.7.2 были добавлены, так что я должен иметь доступ к этой функции языка.

+1

Может быть [этот вопрос SO]] (http://stackoverflow.com/questions/10766112/c11-i-can-go-from-multiple-args-to-tuple-but-can-i-go-from -tuple-to-multiple) может помочь. – maverik

+0

Я еще не уверен, что проблема заключается в вызове базового конструктора, который немного ограничен соглашениями о вызовах, поэтому мое первое чтение - это то, что не будет работать, но позвольте мне рассмотреть его и посмотреть, могу ли я его перекрутить, чтобы соответствовать тому, что я Я ищу. – TimeHorse

+0

Вы можете эмулировать «кусочный» конструктор 'std :: pair'. –

ответ

2

http://cpptruths.blogspot.fr/2012/06/perfect-forwarding-of-parameter-groups.html

решение Davidbrcz, как указано в его блоге выше было достаточно, чтобы решить мою загадку. Решение довольно сложное, поэтому я направлю его на его страницу, но основная идея состоит в том, чтобы «на лету» создать числовой индексный кортеж, à la std :: maketuple (0, 1, 2, ...), где кортеж содержит каждый из индексов различных членов кортежа, который вам нужно перечислить. Тогда вы просто использовать:

M(std::forward<ArgM>(std::get<IdxM>(argm))...) 

Для М, как С или H в примере выше, и ArgM аргументы в М и IdxM одинаково размера кортежа индексов.Поскольку списки имеют одинаковую длину, список выставляется в параметры в тандеме, а кортеж распаковывается.

Ограничение состоит в том, что вы хотите, чтобы сложный шаг построения индексации был скрыт как деталь реализации, вам нужно использовать делегирование конструктора, чтобы публичный конструктор взял два набора, которые затем делегируют частному конструктору, который принимает 2 значения кортежей и 2 индексных кортежа. GCC 4.7.2 поддерживает делегированные конструкторы, но 4.6.3 этого не делает.

Чтобы обойти эту проблему, вам нужно сделать конструктор 4-параметра (2 наборов значений, 2 кортежей индексов) общественные и затем я написал макрос для заполнения параметров индекса кортежа:

#if __GNUC__ < 4 || __GNUC_MINOR__ <= 6 
#define ZEROPARAM , detail::make_indices<>::type() 
#define ONEPARAM , detail::make_indices<int>::type() 
#define TWOPARAM , detail::make_indices<int, int>::type() 
#define THREEPARAM , detail::make_indices<int, int, int>::type() 
#define FOURPARAM , detail::make_indices<int, int, int, int>::type() 
#define FIVEPARAM , detail::make_indices<int, int, int, int, int>::type() 
#define SIXPARAM , detail::make_indices<int, int, int, int, int, int>::type() 
#define SEVENPARAM , detail::make_indices<int, int, int, int, int, int, int>::type() 
#define EIGHTPARAM , detail::make_indices<int, int, int, int, int, int, int, int>::type() 
#define NINEPARAM , detail::make_indices<int, int, int, int, int, int, int, int, int>::type() 
#define TENPARAM , detail::make_indices<int, int, int, int, int, int, int, int, int, int>::type() 
#else // __GNUC__ < 4 || __GNUC_MINOR__ <= 6 
#define ZEROPARAM 
#define ONEPARAM 
#define TWOPARAM 
#define THREEPARAM 
#define FOURPARAM 
#define FIVEPARAM 
#define SIXPARAM 
#define SEVENPARAM 
#define EIGHTPARAM 
#define NINEPARAM 
#define TENPARAM 
#endif // __GNUC__ < 4 || __GNUC_MINOR__ <= 6 

И затем добавьте соответствующий макрос, следующий за конструкцией данного Тестера, по крайней мере, пока есть еще люди на GCC 4.6.3, пока я работаю, чтобы заставить всех по крайней мере 4.7.2 и предпочтительнее 4.8.1. :)

Мне жаль, что я не могу дать кредит Davidbrcz для решения, но, по крайней мере, это может быть полезно для людей, сталкивающихся с аналогичной проблемой, чтобы применить свое решение в своем конкретном случае. Главное - скопировать его класс шаблона make_indices для выполнения фактической работы; остальное - это торт!