2009-10-02 3 views
10

Pamiętam seing coś takiego zostało zrobione:Lista argumentów szablonu o zmiennej długości?

template <ListOfTypenames> 
class X : public ListOfTypenames {}; 

czyli X dziedziczy z listy zmiennej długości typenames przekazywane jako argumenty szablonów. Oczywiście ten kod jest hipotetyczny.

Nie mogę znaleźć żadnego odniesienia do tego. Czy to możliwe? Czy to jest C++ 0x?

Odpowiedz

23

Możesz to zrobić w bieżącym C++. Dajesz szablonowi „wystarczająco” dużą liczbę parametrów, i dać im domyślne:

class nothing1 {}; 
class nothing2 {}; 
class nothing3 {}; 

template <class T1 = nothing1, class T2 = nothing2, class T3 = nothing3> 
class X : public T1, public T2, public T3 {}; 

Albo można uzyskać bardziej wyrafinowane i użyć rekursji. Najpierw do przodu zadeklarować szablonu:

class nothing {}; 

template <class T1 = nothing, class T2 = nothing, class T3 = nothing> 
class X; 

Następnie Specjalizujemy się w przypadku, gdy wszystkie parametry są domyślnie:

template <> 
class X<nothing, nothing, nothing> {}; 

Wtedy właściwie określić ogólny szablon (który wcześniej masz tylko do przodu -deklarowane):

template <class T1, class T2, class T3> 
class X : public T1, public X<T2, T3> 

Zauważ, jak w klasie bazowej dziedziczysz X, ale tęsknisz za pierwszym parametrem. Więc wszyscy przesuwają się wzdłuż jednego miejsca. W końcu wszystkie będą wartościami domyślnymi, a specjalizacja zostanie uruchomiona, co niczego nie odziedziczy, tym samym kończąc rekursję.

Aktualizacja: właśnie miałem dziwne uczucie, bym pisał coś tak przed, and guess what...

+0

można też użyć tylko jednego „nic” class – sellibitze

+0

@sellibitze - używam korzystanie tylko jeden „nic” klasa w wersja rekursywna. Nie możesz użyć tej samej klasy dla wartości domyślnych w wersji nierekurencyjnej, ponieważ dostaniesz błędy "nic już nie jest klasą bezpośrednią". –

+0

Nie rozumiem: dlaczego pomijasz pierwszy parametr podczas dziedziczenia z X? – Gili

19

brzmi jak odnosimy się do C++ 0x Variadic Templates. Ten sam efekt można osiągnąć również za pomocą konstruktora Alexandrescu TypeList z Loki.

Wierzę, że składnia szablonu variadic, o której mowa, wyglądałaby następująco.

template <typename...T> 
class X : public T... {}; 
+13

Jeśli się nie mylę, musisz również rozpakować typ: 'public T ... {};' – UncleBens

2

Zmienna liczba szablonów jest częścią następnego standardu C++. Jednak możesz go posmakować, jeśli używasz GCC (od wersji 4.3). Oto list of available C++0x features in GCC. Szukasz Variadic Templates.

Nawiasem mówiąc, jeśli potrzebujesz formalnego odniesienia do tego, jak osiągnąć mechanizm dziedziczenia opisany przez Earwicker, jest on w książce C++ Templates.

4

Jak już inni odpowiedzieli, szablony variadic są częścią następnego standardu, ale mogą być emulowane w bieżącym C++. Jednym wygodnym narzędziem do tego jest użycie biblioteki Boost.MPL. W swoim kodzie zapisujesz pojedynczy parametr szablonu (nazwijmy go "Typelist"), a użytkownicy twojego szablonu owijają typelistę w sekwencji MPL. Przykład:

#include "YourType.h" 
#include "FooBarAndBaz.h" 
#include <boost/mpl/vector.hpp> 

YourType<boost::mpl::vector<Foo, Bar, Baz> > FooBarBaz; 

Przy realizacji "YourType", możesz uzyskać dostęp do elementów w Typelist z różnymi metafunkcjami. Na przykład: at_c<Typelist, N> jest jednym z elementów listy na poziomie N.Jako inny przykład, „X” klasa w swoim pytaniu może być napisany z inherit_linearly jak:

//Warning: Untested 
namespace bmpl = boost::mpl; 
template<class Typelist> 
class X : bmpl::inherit_linearly<Typelist, bmpl::inherit<bmpl::_1, bmpl::_2> >::type 
{ 
... 
};