2013-07-28 2 views
2

Мне нужно реализовать некоторый Variadic шаблонный контейнерный класс с гетерогенными элементами, который позволяет выполнять итерацию этими элементами. Моя первая мысль, это сделать класс с членом станд :: кортеж с переменным числом аргументов, но получить элементы из кортежа по массиву манере (с помощью петли) невозможно:Неоднородный контейнер шаблонов Variadic

struct A {void prnt(){std::cout<<"A\n";} };  
struct B {void prnt(){std::cout<<"B\n";} };  
struct C {void prnt(){std::cout<<"C\n";} }; 

template<typename...Arg> 
struct Prc 
{ 
    Prc() : NumElems(sizeof...(Arg)), mems(std::make_tuple(Arg()...)){} 

    int NumElems; 
    std::tuple<Arg...> mems; 

    void process() 
    { 
     for(int i=0; i<NumElems; ++i) 
     std::get<i>(mems).prnt();//It's forbidden: "i" must be a constant 
    } 
}; 

int main() 
{ 
    Prc<A,B,C> obj; 
    obj.process(); 
} 

Любые идеи?

P.S. Я не хочу использовать подталкивание разнородных контейнеров, как импульса :: варианта или повышения :: любой

+2

(http://loungecpp.wikidot.com/tips-and-tricks:indices) – Xeo

+0

Я не уверен, что вы подразумеваете под " массивным образом ». – jsp

ответ

3

Вот это делается с помощью indicies: [.] Индексы

namespace detail 
{ 
    template <int... Is> 
    struct index { }; 

    template <int N, int... Is> 
    struct gen_seq : gen_seq<N - 1, N - 1, Is...> { }; 

    template <int... Is> 
    struct gen_seq<0, Is...> : index<Is...> { }; 
} 

template <typename...Args> 
struct Prc 
{ 
    std::tuple<Args...> mems; 

    template <int... Is> 
    void process(detail::index<Is...>) 
    { 
     auto l = { (std::get<Is>(mems).prnt(), 0) ... }; 
    } 

    void process() 
    { 
     process(detail::gen_seq<sizeof...(Args)>()); 
    } 
}; 
+0

Почему я не могу заменить «пространство имен»? В этом случае он не компилируется. – gorill

+0

@gorill Извините, я сделал несколько ошибок в своем исходном коде. Я обновил свой ответ, пожалуйста, посмотрите. – 0x499602D2

+0

Это нормально))) Я их нашел))) – gorill

1

Вот код, который перебирает кортеж:

struct A { void print() { clog << "A" << endl; } }; 
struct B { void print() { clog << "B" << endl; } }; 
struct C { void print() { clog << "C" << endl; } }; 

template<unsigned N> 
struct iter 
{ 
    template<typename T> 
    static void f (T &t) 
    { 
     iter<N-1>::f (t); 
     get<N> (t).print(); 
    } 
}; 

template<> 
struct iter<0> 
{ 
    template<typename T> 
    static void f (T &t) 
    { 
     get<0> (t).print(); 
    } 
}; 

И коды вызова:

tuple <A,B,C> t; 
    iter<tuple_size<decltype(t)>::value-1>::f (t); 

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

 Смежные вопросы

  • Нет связанных вопросов^_^