Распаковка пакета параметров args в конструктор каждого класса, определенного в шаблоне с переменными параметрами - PullRequest
4 голосов
/ 08 октября 2011

Я пытаюсь создать класс, который наследует от нескольких классов (как определено с помощью шаблона переменной) и, для каждого класса, передает один и тот же пакет параметров аргументов в конструктор каждого класса. Однако кажется, что я не могу распаковать как шаблон переменных классов, так и пакет параметров args.

У меня есть класс:

template<class... __Policies>
class GenericPolicyAdapter : public __Policies...{

С конструктором:

template<class... __Args>
GenericPolicyAdapter( __Args... args ) : __Policies( args... ){

и тест:

GenericPolicyAdapter<T1,T2> generic_policy_adapter( arg1, arg2, arg3 );

gcc не работает с:

error: type ‘__Policies’ is not a direct base of ‘GenericPolicyAdapter<T1,T2>’

где __Policies = T1, T2

Чтобы уточнить, я, по сути, пытаюсь сделать:

GenericPolicyAdapter : public T1, public T2
{
  public:
    template<class... __Args>
    GenericPolicyAdapter( __Args... args ) : T1( args... ), T2( args... ){}
};

, но с T1 и T2, выведенными из __Policies

Есть идеи? Похоже, что gcc рассматривает __Policies как один тип, а не как список типов. Заранее спасибо!


Edit:

Я должен уточнить, что я использую gcc / g ++ 4.4.5.

Говард Хиннант предложил сделать:

template<class... __Args>
    GenericPolicyAdapter( __Args... args )
        : __Policies( args...)...
    {}

Однако, с gcc / g ++ 4.4.5 это дает invalid use of pack expansion expression. Здорово, что это работает в OSX / clang, но есть ли способ сделать это в gcc / g ++?

Ответы [ 3 ]

16 голосов
/ 08 октября 2011

"..." очень похоже на "typename".Вы просто должны продолжать агрессивно разбрасывать его, пока все не скомпилируется.: -)

template<class... __Policies>
class GenericPolicyAdapter
    : public __Policies...
{
public:
    template<class... __Args>
        GenericPolicyAdapter( __Args... args )
            : __Policies( args...)...
        {}
};

struct T1
{
    T1(int, int, int) {}
};

struct T2
{
    T2(int, int, int) {}
};

int main()
{
    GenericPolicyAdapter<T1,T2> generic_policy_adapter( 1, 2, 3 );
}
6 голосов
/ 10 октября 2011

Из http://www.open -std.org / jtc1 / sc22 / wg21 / docs /apers / 2011 / n3242.pdf

14.5.3 Шаблоны Variadic [темп.variadic]

5 Пакет параметров, имя которого отображается в шаблоне расширения пакета, расширяется этим расширением пакета. Внешний вид имени пакета параметров расширяется только расширением самого внутреннего пакета.Шаблон расширения пакета должен называть один или несколько пакетов параметров, которые не раскрываются вложенным расширением пакета. Все пакеты параметров, развернутые расширением пакета, должны иметь одинаковое количество указанных аргументов.Внешний вид имени пакета параметров, который не расширен, является некорректным.[Пример:

template<typename...> struct Tuple {};
template<typename T1, typename T2> struct Pair {};

template<class ... Args1> struct zip {
  template<class ... Args2> struct with {
    typedef Tuple<Pair<Args1, Args2> ... > type;
  };
};

typedef zip<short, int>::with<unsigned short, unsigned>::type T1;
    // T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>>
typedef zip<short>::with<unsigned short, unsigned>::type T2;
    // error: different number of arguments specified for Args1 and Args2

template<class ... Args> void g(Args ... args) {
  f(const_cast<const Args*>(&args)...); // OK: “Args” and “args” are expanded
  f(5 ...); // error: pattern does not contain any parameter packs
  f(args); // error: parameter pack “args” is not expanded
  f(h(args ...) + args ...); // OK: first “args” expanded within h, second
  // “args” expanded within f
}

- конец примера]

Я думаю, что f(h(args ...) + args ...); может быть ближайшим стандартным примером, который вы получите.

Обратите внимание, что есливы сделали:

template<class... __Policies>
class GenericPolicyAdapter
    : public __Policies...
{
public:
    template<class... __Args>
        GenericPolicyAdapter( __Args... args )
            : __Policies(args)... // See the missing '...' ?
        {}
};

Вы бы вытащили один аргумент из списка параметров конструктора и применили бы их к базовым конструкторам.Ключ заключается в расширении __Policies после расширения args.

0 голосов
/ 10 октября 2011

Как упомянуто выше в комментарии, gcc на сегодняшний день довольно слаба в поддержке вариабельных шаблонов.Особенно, когда речь идет о расширении пакета параметров.Gcc 4.6 не может даже развернуть пакеты в списки фиксированной длины.

Следующий код - возможный обходной путь, основанный на гораздо более сложном способе обхода тех ограничений, которые я обычно использую.Он будет компилироваться только на самом последнем gcc из svn:

#include <iostream>

template<class T>
struct derive : T
{
    template<class... A>
    derive( A... a ) :
        T(a...)
    {
    }
};

template<class X, class... T>
struct deriver;

template<class X>
struct deriver<X> :
    derive<X>
{
    template<class... A>
    deriver( A... a ) :
        derive<X>(a...)
    {
    }
};

template<class X, class... T>
struct deriver : 
    derive<X>, deriver<T...>
{
    template<class... A>
    deriver( A... a ) :
        derive<X>(a...), deriver<T...>(a...)
    {
    }
};

template<class... __Policies>
class GenericPolicyAdapter
    : public deriver<__Policies...>
{
public:
    template<class... __Args>
        GenericPolicyAdapter( __Args... args )
            : deriver<__Policies...>( args...)
        {}
};

#define BARK std::cout << __PRETTY_FUNCTION__ << "\n"
struct T1
{
    T1(int, int, int) {BARK;}
};

struct T2
{
    T2(int, int, int) {BARK;}
};

int main()
{
    GenericPolicyAdapter<T1,T2> generic_policy_adapter( 1, 2, 3 );
}

Все выпущенные gccs будут задыхаться от этого с:

sorry, unimplemented: cannot expand 'T ...' into a fixed-length argument list

, что может также обойтись при еще большей косвенности,но это должно быть хорошей отправной точкой (в зависимости от того, сколько вы хотите переносимости).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...