2011-09-12 14 views
5

Dato un modello di comeè possibile la creazione di istanze di template espliciti ricorsivi?

template<int dim> class Point { ... }; 

questo modello è possibile creare un'istanza in modo esplicito come

template class Point<0>; 
template class Point<1>; 
template class Point<2>; 
template class Point<3>; 

invece di istanziare ogni template singolarmente come sopra, vorrei istanziare loro in modo ricorsivo con una sola chiamata come

template class RecursiveInstantiate<Point, 3>; 

dove RecursiveInstantiate<T, i> dovrebbe creare un'istanza T<i>, T<i-1>, ..., T<0>. È in qualche modo possibile creare una tale classe RecursiveInstantiate? Se non è possibile, conosci un modo per farlo con il preprocessore?

In effetti sono interessato a generalizzare questo per le classi con più parametri di modello come Node<int i1,int i2,int i3> per tutte le combinazioni di i1, i2, i3 in {0,1,2,3}. Ma spero di essere in grado di elaborare questa seconda parte da solo.

Qualsiasi consiglio, anche una spiegazione del perché è impossibile ciò che voglio ottenere è apprezzato.


Aggiornamento: Grazie per i vostri commenti finora. Ora vedo più chiaramente dove si trova il problema. La riga

template class Point<3>; 

crea un'istanza del modello ed esporta i suoi simboli nel file oggetto. Un'esemplificazione della forma

template class RecursiveInstantiate<Point, 3>; 

può istanziare le classi class Point<3>, class Point<2>, .... A quanto pare questo accade solo a livello locale però. I modelli non vengono esportati nel file oggetto. Forse dovrò cercare una soluzione usando il preprocessore.

Come vedo ora che non ho fatto la mia domanda abbastanza precisamente all'inizio, apprezzo le vostre risposte e quelle selezionate come corrette.

Nota: Sto provando questo su linux con g ++/clang come compilatori.

risposta

8

si potrebbe fare un po 'di classe Instantiator:

template <unsigned int N> struct Instantiator 
{ 
    Point<N> p; 
    Instantiator<N-1> i; 
}; 

template <> struct Instantiator<0> 
{ 
    Point<0> p; 
}; 

Poi basta aggiungere uno esplicita esemplificazione: template struct Instantiator<81>;

È possibile estendere questa idea lessicografico a qualsiasi numero di parametri integrali.


Come dice @Georg, Facciamo generico:

template <template <unsigned int> class T, unsigned int N> struct Instantiator 
{ 
    T<N> t; 
    Instantiator<T, N-1> i; 
}; 

template <template <unsigned int> class T> struct Instantiator<T, 0> 
{ 
    T<0> t; 
}; 

template struct Instantiator<Point, 82>; 
+0

Rendilo 'template struct I {T p; I ; }; ... '. Inoltre, l'uso di meta-algoritmi e meta-funzioni potrebbe evitare il conteggio dei parametri hard-coding (vedere cosa fa Boost.MPL). –

+0

@Georg: Mi piace il tuo stile! –

+0

Questa soluzione sembra molto bella, mi piace molto la tua soluzione generica. Ho ancora difficoltà a farlo funzionare. L'approccio si compila bene, sì, ma in qualche modo i simboli per "Punto <0>" non vengono esportati nel file oggetto, che è ciò che il codice 'classe modello Punto <0>;' sta facendo. Dovrò indagare su questo ulteriore domani. Sto usando g ++/clang su Linux, ma non sono sicuro se questo è specifico per la mia architettura. –

4

Potete farlo in questo modo:

template<int dim> struct Point { 
    static const int val = dim; 
    Point<dim - 1> p; 
}; 

template<> struct Point<0> { ... }; 

che crea una specializzazione modello per il parametro di template quando è 0 così la ricorsione si ferma lì, e quando si crea un'istanza di uno come questo:

Point<4> 

Si crea da Point<4> a Point<0>. Quindi puoi fare

Point<4>::val 

per accedere al valore di quello particolare.

+3

che richiede la modifica e avere il controllo sulla definizione di 'Point', però. –

+0

@Kerrek il concetto può essere facilmente esteso per essere utilizzato senza modificare 'Punto'. –

+0

Questo approccio non ha funzionato per me. Se istanzio 'classe template Punto <4>;' solo i simboli per 'Punto <4>' vengono esportati nel file oggetto, non gli altri simboli, sebbene in effetti la ricorsione sia eseguita correttamente dal compilatore. –

Problemi correlati