2013-03-19 29 views
16

Mam szablon funkcji takich jak to:Iteracja nad typu zmiennej liczbie argumentów szablonu Parametry

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

Nie mogę korzystać Boost.MPL. Czy możesz pokazać, jak to zrobić bez rekursji?

+2

[To Q A] (http://stackoverflow.com/questions/14261183/how-to-make-generic-computations-over-heterogeneous-argument-packs-of-a-variadic) powinna pomóc. –

+1

Nie mam żadnych argumentów w mojej funkcji, odwołanie do rozwiązania ma argumenty. – user1095108

+0

Kogo to obchodzi, jeśli są kłótnie? Chodzi o rozszerzenie variadics, działa tak samo. –

Odpowiedz

17

What Xeo said. Aby utworzyć kontekst Dodatek użyłem liście argumentów funkcji, która nic nie robi (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; 
} 

Ten program wypisuje 111.

+0

Moje rozwiązanie: '[] (...) {} ((A :: var = 1) ...);'. Może zmienić swoje i akceptuję? W rzeczywistości jest to Xeo ... – user1095108

+0

@ user1095108 Nice one, added. – jrok

+0

@ user1095108 Mimo, że powinieneś zachować ostrożność przy elipsie, jest to niezdefiniowane zachowanie, aby przekazać im typ inny niż POD. Nie jestem pewien, czy ma to zastosowanie w tym przypadku, ale nadal. – jrok

5

Jako przykład, załóżmy, że chcesz wyświetlić każdy A :: var. Widzę trzy sposoby na osiągnięcie tego, co ilustruje poniższy kod.

Jeśli chodzi o opcję 2, należy zauważyć, że kolejność przetwarzania elementów nie jest określona przez normę.

#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

Myślę, że możesz zrobić jeszcze lepiej dzięki:' std :: initializer_list {(A :: var = 1) ...}; ' – user1095108

Powiązane problemy