2013-03-19 16 views
16

Ho un modello di funzione come questa:iterazione sopra il tipo del modello variadic parametri

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

non posso usare Boost.MPL. Puoi per favore mostrare come farlo senza ricorsione?

+2

[Questa Q & A] (http://stackoverflow.com/questions/14261183/how-to-make-generic-computations-over-heterogeneous-argument-packs-of-a-variadic) dovrebbe aiutare. –

+1

Non ho argomenti nella mia funzione, la soluzione di riferimento ha argomenti. – user1095108

+0

Chi se ne importa se ci sono argomenti? Si tratta di espandere le variadiche, funziona allo stesso modo. –

risposta

17

Che cosa Xeo said. Per creare un contesto per Expansion Pack ho usato la lista degli argomenti di una funzione che non fa nulla (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; 
} 

Questo programma stampe 111.

+0

La mia soluzione: '[] (...) {} ((A :: var = 1) ...);'. Cambia forse il tuo e accetto? In realtà, è Xeo's ... – user1095108

+0

@ user1095108 Bello, aggiunto. – jrok

+0

@ user1095108 Anche se dovresti fare attenzione con l'ellissi, è un comportamento indefinito passare loro un tipo non POD. Non sono sicuro se si applica in questo caso, ma ancora. – jrok

5

Ad esempio, si supponga di voler visualizzare ogni A :: var. Vedo tre modi per ottenere questo risultato, come illustrato nel seguente codice.

Per quanto riguarda l'opzione 2, si noti che l'ordine in cui gli elementi vengono elaborati non è specificato dallo standard.

#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

Penso che potresti fare ancora meglio con:' std :: initializer_list {(A :: var = 1) ...}; ' – user1095108

Problemi correlati