2013-03-19 2 views
16

У меня есть шаблон функции вроде этого:Перебор типа VARIADIC шаблона параметры

template <class ...A> 
do_something() 
{ 
    // i'd like to do something to each A::var, where var has static storage 
} 

Я не могу использовать Boost.MPL. Не могли бы вы показать, как это сделать без рекурсии?

+2

[Это Q & A] (http://stackoverflow.com/questions/14261183/how-to-make-generic-computations-over-heterogeneous-argument-packs-of-a-variadic) должно помочь. –

+1

У меня нет аргументов в моей функции, ссылка имеет аргументы. – user1095108

+0

Кого волнует, если есть аргументы? Речь идет о расширении вариаций, работает одинаково. –

ответ

17

Xeo said. Для того, чтобы создать условия для расширения пакета я использовал список аргументов функции, которая ничего не делает (dummy):

#include <iostream> 
#include <initializer_list> 

template<class...A> 
void dummy(A&&...) 
{ 
} 

template <class ...A> 
void do_something() 
{ 
    dummy((A::var = 1)...); // set each var to 1 

    // alternatively, we can use a lambda: 

    [](...){ }((A::var = 1)...); 

    // or std::initializer list, with guaranteed left-to-right 
    // order of evaluation and associated side effects 

    auto list = {(A::var = 1)...}; 
} 

struct S1 { static int var; }; int S1::var = 0; 
struct S2 { static int var; }; int S2::var = 0; 
struct S3 { static int var; }; int S3::var = 0; 

int main() 
{ 
    do_something<S1,S2,S3>(); 
    std::cout << S1::var << S2::var << S3::var; 
} 

Эта программа печатает 111.

+0

Мое решение: '[] (...) {} ((A :: var = 1) ...);'. Возможно, изменишься, и я согласен? На самом деле, это Xeo's ... – user1095108

+0

@ user1095108 Ницца, добавлено. – jrok

+0

@ user1095108 Наверху, вы должны быть осторожны с многоточием, это неопределенное поведение, чтобы передать им не-POD-тип. Я не уверен, что это применимо в этом случае, но все же. – jrok

5

В качестве примера предположим, что вы хотите отображать каждый A :: var. Я вижу три способа сделать это, как показывает приведенный ниже код.

Что касается варианта 2, обратите внимание, что порядок, в котором элементы обрабатываются, не указан стандартом.

#include <iostream> 
#include <initializer_list> 

template <int i> 
struct Int { 
    static const int var = i; 
}; 

template <typename T> 
void do_something(std::initializer_list<T> list) { 
    for (auto i : list) 
     std::cout << i << std::endl; 
} 

template <class... A> 
void expand(A&&...) { 
} 

template <class... A> 
void do_something() { 

    // 1st option: 
    do_something({ A::var... }); 

    // 2nd option: 
    expand((std::cout << A::var << std::endl)...); 

    // 3rd option: 
    { 
     int x[] = { (std::cout << A::var << std::endl, 0)... }; 
     (void) x; 
    } 
} 

int main() { 
    do_something<Int<1>, Int<2>, Int<3>>(); 
} 
+0

Я думаю, вы могли бы сделать еще лучше:' std :: initializer_list {(A :: var = 1) ...}; ' – user1095108

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