2010-01-28 11 views
40

Ver título. Tengo una plantilla. Quiero forzar una instancia particular de una plantilla para crear instancias. ¿Cómo hago esto?¿Cómo fuerzo una instancia particular de una plantilla C++ para crear instancias?

Más específicamente, ¿puede forzar una clase de plantilla abstracta para instanciar?


Podría elaborar porque tengo la misma pregunta. En mi caso, estoy construyendo una biblioteca, algunas de las implementaciones de plantillas son grandes e incluyen muchas cosas, pero solo se generan para un par de tipos. Quiero compilarlos en la biblioteca y exportar todos los métodos, pero no incluir el encabezado con el código en todas partes.

es decir:

template<class T> 
OS_EXPORT_DECL class MyTmpl 
{ 
    T *item1; 
public: 
    inline T *simpleGetT() { return(item1); } /* small inline code in here */ } 
    T *doSomeReallyBigMergeStuff(T *b); // note only declaration here 
}; 

// *** implementation source file only seen inside library 

template<class T> 
MyTmpl<T>::doSomeReallyBigMergeStuff(T *b) 
{ 
    ... a really big method, but don't want to duplicate it, 
     so it is a template ... 
} 

pude de referencia supuesto todos los métodos dentro de la biblioteca que les obligaría a compilar y exportación, pero el deseo no es añadir código de un-necesario para la biblioteca como el argumento formateo de los elementos y el código para llamarlos, etc.

????? específicamente estoy construyendo la biblioteca para varias versiones de MSC y GCC y compiladores de inteligencia.

+0

¿Puede dar un ejemplo? ¿A qué te refieres con "instanciar una clase de plantilla abstracta"? – jalf

Respuesta

45

No se puede forzar plantillas genéricas para instanciar, el compilador solo puede generar código si el tipo es completamente conocido.

Forzar una instanciación se hace proporcionando todo tipo de forma explícita:

template class std::vector<int>; 

Comeaus template FAQ abarca los temas relacionados con cierto detalle.

+0

tenga en cuenta que debe hacer esto después de que todas las plantillas y el código para ellos hayan sido declarados seguros. – peterk

+18

@peterk "declarado como seguro" me hizo preguntarme durante unos 20 segundos. Entonces me di cuenta "después de ... sido declarado, _para estar seguro_". - lol – sehe

+1

Esto es realmente un error de sintaxis, al menos en gcc 4.1; debería ser 'template class std :: vector ' (la respuesta de Alexander a continuación es correcta) – Redmumba

-1

clase abstracta no puede ser instantiated.you probablemente querrá hacer algo en la línea de:

Abstract *a = new Implementation(...); 

Para obligar a instancias de plantilla, plantilla de la llamada con los parámetros de plantilla:

std::max<int>(...); 
std::pair<int, string>(...); 
0

Si entiendo su pregunta correctamente, tiene una clase de plantilla, y desea obligar al compilador a generar el código para usar con algún tipo específico. Por ejemplo, es posible que desee asegurarse de que el código para std :: vector <int> exista en su programa.

La mejor manera de asegurar esto es simplemente construir una instancia de la clase:

void EnsureInstantiation() 
{ 
    std::vector<int> intvector; 
    std::vector<boo> boolvector; 
    /// etc. 
} 

El truco es que no tienen ni siquiera para llamar EnsureInstantiation cualquier parte del código. Solo asegúrese de que no sea estático o de lo contrario el compilador puede optimizarlo.

1

Puede forzar la creación de instancias utilizando la plantilla con el parámetro deseado. Por ejemplo, podría definir una función utilizando todos los métodos necesarios:

void force_int_instance() { 
    Abstract<int> *a; 
    a->some_method(); 
    a->some_other_method(1, 2, 3); 
} 

No es necesario llamar a la función que en realidad en cualquier lugar, así que no es un problema que el puntero no se ha inicializado. Pero el compilador tiene que suponer que la función puede ser llamada desde otro archivo objeto, por lo que tiene que crear una instancia de la plantilla.

-2

Voy a responder a lo que creo que quiso decir, no a lo que dijo.

Supongo que el problema es una de dos cosas. El primero es que tiene un código en una plantilla que no se compila cuando compila el archivo de la plantilla, lo que puede ser muy molesto. Eso se puede arreglar en la configuración del compilador.

La otra es que desea tener algo especial para un tipo en particular, quizás para depurarlo. Eso se llama instanciación explícita pero en realidad no instancia nada, solo asegura que siempre se defina después de ese punto.

http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/topic/com.ibm.vacpp6m.doc/language/ref/clrc16explicit_instantiation.htm

+0

Nunca intentes y respondas lo que piensas que alguien quiso decir. – Owl

39

Lo que también se puede probar es explícita de instancias:

template class vector<int>;     // class 
template int& vector<int>::operator[](int); // member 
template int convert<int,double>(double);  // function 
+6

Hasta que llegué a esta publicación intenté durante días usar la plantilla <> y no pude entender cuál era el problema. Usar solo "plantilla" sin corchetes angulares funcionó perfectamente. – twerdster

+0

downvoter, me gustaría comentar? –

Cuestiones relacionadas