2012-10-10 14 views
5

Przepraszamy za zawiłe pytanie, ale w zasadzie pomysł jest bardzo prosty. Mam zmiennej liczbie argumentów klasy formy:Czy jest możliwe zdefiniowanie szablonu klasy variasic C++ 11, którego liczność parametru variadic zależy od parametru szablonu integer?

template<class P1, class P2, class ... P3s> 
class A 
{ 
    ... 
}; 

ja jak mieć Generator Klasy który przyjmuje szablonu całkowitą parametru N oraz instancję klasy z parametrów N P3S. Jak:

template<class P1, class P2, class P3, int N> 
class GenA : /* somehow */ : public A<P1, P2, /* N times */ P3, P3, ...> 
{ 
    ... 
}; 

więc wykorzystanie byłoby:

// Generates A<Class1, Class2, Class3, Class3, Class3> 
GenA<Class1, Class2, Class3, 3> a; 

Próbowałem już to robić z kompilacji rekursji czasu i częściowej specjalizacji

template <class P1, class P2, int N, class P3> 
class GenA : public GenA<P1, P2, N-1, P3, P3> 
{ 
    ... 
} 

template <class P1, class P2, int N, class ... P3s> 
class GenA<P1, P2, 0, P3s ...> : public A<P1, P2, P3s, ...> 
{ 
    ... 
} 

jednak C++ 11 nie rozpoznaje drugi szablon jest specjalizacją pierwszego (ponieważ w rzeczywistości jest inny) i nigdy nie dostaje się do podstawowego przypadku rekursji (przestaje narzekać na zbyt dużą liczbę rekurencji). Jakieś pomysły?

Dzięki
Tunnuz

+0

Wydaje się trudne bez nadmiernych specjalizacji szablonów. –

+0

Po wybraniu jednej z odpowiedzi możesz podać punkt odniesienia dla rozwiązań? – pmr

Odpowiedz

5
template<class P1, class P2, class... P3s> 
class A {}; 

template<class... Ps> 
struct TypeList {}; 

template<class P1, class P2, class P3, unsigned N, class P> struct GenHelp; 

template<class P1, class P2, class P3, class... Ps> 
struct GenHelp<P1, P2, P3, 0, TypeList<Ps...> > 
{ 
    typedef A<P1, P2, Ps... > AType; 
}; 

template<class P1, class P2, class P3, unsigned N, class... Ps> 
struct GenHelp<P1, P2, P3, N, TypeList<Ps...> > : public GenHelp<P1, P2, P3, N-1, TypeList<P3, Ps...> > 
{}; 

template<class P1, class P2, class P3, unsigned N> 
class GenA : public GenHelp<P1, P2, P3, N, TypeList<> >::AType 
{}; 
+0

Genialny! Biorę to, ponieważ jest podobny do tego, co próbowałem zrobić. – tunnuz

5

Można użyć zmiennej liczbie argumentów parametrów szablonu szablon, aby to zrobić. W tej implementacji po prostu rozpoczynamy od zestawu argumentów składającego się z P1 i P3 i kontynuujemy jego rozszerzanie. Na koniec tworzymy instancję szablonu szablonu variadic z tym pakietem argumentów.

template<class P1, class P2, class ... P3s> 
struct A {}; 

template<template<class... Args> class AT, typename P3, int N, 
     typename... Already> 
struct GenAImpl { 
    typedef typename GenAImpl<AT, P3, N - 1, Already..., P3>::type type; 
}; 

template<template<class... Args> class AT, typename P3, 
     typename... Already> 
struct GenAImpl<AT, P3, 0, Already...> { 
    typedef AT<Already...> type; 
}; 


template<class P1, class P2, class P3, int N> 
struct GenA : GenAImpl<A, P3, N, P1, P2> 
{}; 

int main() 
{ 
    GenA<int, double, float, 3>::type X; 
    return 0; 
} 

Należy pamiętać, że dołączenie do listy często jest to zły pomysł (przynajmniej w językach rzeczywistym funkcjonalnych, nie mam pojęcia, czy to rzeczywiście wpływ C++ wydajność kompilator) i jesteś lepszy z consing razem i cofnij go na końcu.

+0

Ale ja również poprowadzę to rozwiązanie. – tunnuz

Powiązane problemy