2011-09-12 18 views
5

dieron una plantilla como¿es posible la creación de instancias de plantilla explícita recursiva?

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

esta plantilla se pueden crear instancias de forma explícita como

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

en lugar de crear instancias de todas las plantillas de forma individual como la de arriba, me gustaría crear instancias de ellos de forma recursiva con una llamada como

template class RecursiveInstantiate<Point, 3>; 

donde RecursiveInstantiate<T, i> instanciaría T<i>, T<i-1>, ..., T<0>. ¿Es de alguna manera posible crear una clase de este tipo RecursiveInstantiate? Si no es posible, ¿conoce una forma de hacerlo con el preprocesador?

De hecho, estoy interesado en generalizar esto para las clases con múltiples parámetros de plantilla como Node<int i1,int i2,int i3> para todas las combinaciones de i1, i2, i3 en {0,1,2,3}. Pero espero ser capaz de resolver esta segunda parte yo solo.

Se agradece cualquier consejo, también una explicación de por qué es imposible lo que quiero lograr.


Actualización: gracias por sus comentarios hasta el momento. Ahora veo más claramente dónde está realmente el problema. La línea

template class Point<3>; 

ejemplifica la plantilla y exporta sus símbolos al archivo objeto. Una instancia de la forma

template class RecursiveInstantiate<Point, 3>; 

puede crear instancias de las clases class Point<3>, class Point<2>, .... Al parecer, esto sólo ocurre localmente sin embargo. Las plantillas no se exportan al archivo objeto. Tal vez tendré que buscar una solución usando el preprocesador.

Como veo ahora que al principio no hice mi pregunta con precisión, agradezco sus respuestas y las seleccionadas como correctas.

Nota: Estoy intentando esto en linux con g ++/clang como compiladores.

Respuesta

8

usted podría hacer un poco de clase instanciadoras:

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

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

simplemente añadir una instancias explícita: template struct Instantiator<81>;

Puede ampliar esta idea lexicográfico a cualquier número de parámetros integrales.


Como dice @Georg, vamos a hacer lo genérico:

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

Hazlo 'plantilla struct I {T p; I ; }; ... '. Además, el uso de meta-algoritmos y meta-funciones evitaría el recuento de parámetros de codificación dura (vea lo que hace Boost.MPL). –

+0

@Georg: ¡Me gusta tu estilo! –

+0

Esta solución se ve muy bien, realmente me gusta su solución genérica. Todavía tengo problemas para hacer que esto funcione. El enfoque se compila muy bien, sí, pero de alguna manera los símbolos del 'Punto <0>' no se exportan al archivo objeto, que es lo que haría el código 'clase de plantilla Punto <0>; '. Tendré que investigar esto más mañana. Estoy usando g ++/clang en Linux, pero no estoy seguro de si esto es específico de mi arquitectura. –

4

Puede hacerlo de esta manera:

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

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

que crea una especialización de plantilla para el parámetro de plantilla cuando es 0 por lo que la recursividad se detiene allí, y cuando se ejemplariza uno como este:

Point<4> 

Instancia de Point<4> hasta Point<0>. A continuación, puede hacer

Point<4>::val 

para acceder al valor de ese particular.

+3

que requiere la modificación y que tenga autoridad sobre la definición de 'Point', sin embargo. –

+0

@Kerrek el concepto puede ampliarse fácilmente para ser utilizado sin modificar 'Punto '. –

+0

Este enfoque no funcionó para mí. Si instalo una 'clase de plantilla Point <4>; ', solo los símbolos para' Point <4>' se exportan al archivo objeto, no a los demás símbolos, aunque la recursión se ejecuta correctamente por el compilador. –

Cuestiones relacionadas