2009-10-02 14 views
10

Ricordo seing qualcosa di simile sta facendo:Elenco degli argomenti del modello di lunghezza variabile?

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

che è, X eredita da un elenco di lunghezza variabile dei nomi dei tipi passati come gli argomenti di template. Questo codice è ipotetico, ovviamente.

Non riesco a trovare alcun riferimento per questo, però. È possibile? È C++ 0x?

risposta

23

È possibile farlo nel C++ corrente. Si dà il modello di un numero "abbastanza grande" dei parametri, e si dà loro valori predefiniti:

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

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

Oppure si può ottenere più sofisticati e l'uso ricorsione. Per prima cosa è andata-dichiara il modello:

class nothing {}; 

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

Poi si specializzano per il caso in cui tutti i parametri sono di default:

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

Poi si definiscono correttamente il modello generale (che in precedenza hai solo in avanti -declarato):

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

Nota come nella classe base si eredita X ma si perde il primo parametro. Quindi scivolano tutti insieme in un punto. Alla fine saranno tutti predefiniti, e la specializzazione prenderà il via, che non erediterà nulla, chiudendo così la ricorsione.

Aggiornamento: appena avuto una strana sensazione che avevo postato qualcosa di simile prima, and guess what...

+0

si potrebbe anche utilizzare un solo "nulla" classe – sellibitze

+0

@sellibitze - io uso utilizzare un solo "niente" di classe nella versione ricorsiva. Non è possibile utilizzare la stessa classe per i valori predefiniti nella versione non ricorsiva, poiché si otterranno errori "nulla è già una classe di base diretta". –

+0

Non capisco: perché salti il ​​primo parametro quando erediti da X? – Gili

19

Suona come si fa riferimento a C++ 0x Variadic Templates. È inoltre possibile ottenere lo stesso effetto utilizzando il costrutto TypeList di Alexandrescu da Loki.

Credo che la sintassi del modello variadico in questione sia simile alla seguente.

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

Se non sbaglio, dovrai anche decomprimere il tipo: 'public T ... {};' – UncleBens

2

Il numero variabile di modelli fa parte del successivo standard C++. Tuttavia, è possibile ottenere un assaggio di esso se si utilizza GCC (dalla versione 4.3). Ecco uno list of available C++0x features in GCC. Stai cercando i modelli Variadic.

A proposito, se è necessario un riferimento formale su come ottenere il meccanismo di trasmissione ereditario come descritto da Earwicker, è sul libro C++ Templates.

4

Come altri hanno già risposto, i modelli variadici fanno parte dello standard successivo, ma possono essere emulati nell'attuale C++. Uno strumento utile per questo è utilizzare la libreria Boost.MPL. Nel tuo codice, scrivi un singolo parametro template (chiamiamolo "Typelist"), e gli utenti del tuo template avvolgono la lista di caratteri in una sequenza MPL. Esempio:

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

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

Per l'attuazione di "YourType", è possibile accedere agli elementi in Typelist con vari METAFUNCTIONS. Ad esempio, at_c<Typelist, N> è l'elemento N dell'elenco.Come un altro esempio, la classe "X" nella tua domanda potrebbe essere scritta con inherit_linearly come:

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