2010-03-30 20 views
5

El código de plantilla no se compila hasta que se utiliza la función de plantilla. Pero, ¿dónde guarda el código compilado, se guarda en primer lugar en el archivo de objeto desde el que se utilizó la función de plantilla?plantillas de comprensión de problemas en C++

Por ejemplo, main.cpp está llamando a una función de plantilla desde el archivo test.h, el compilador genera un archivo de objeto main.o, ¿La función de plantilla está dentro del archivo main.o? porque el código de la plantilla no está en línea, ¿verdad?

+0

¿Qué le hace pensar que el código de la plantilla no está en línea? Intente compilar un ejemplo simple con la optimización habilitada, y desmonte el resultado. –

Respuesta

4

Depende totalmente de la implementación del compilador. La mayoría de los compiladores generarán código alrededor, en línea o en archivos cpp-like y luego compilarán con eso. A veces, con la configuración de optimización, algunos compiladores incluso reutilizarán el mismo código en lugar de volver a crearlo para cada cpp.

Así que debe ver el documento de su compilador para obtener más detalles.

+3

Esta es la respuesta correcta real, no la que fue aceptada por el OP. –

0

Siempre está en línea (es decir, siempre es un enlace interno, tiene semántica en línea). De hecho, puede no estar en línea después de todo, al igual que una función en línea, sin embargo, la plantilla no es un código. Es una "plantilla para hacer código". Por lo tanto, normalmente residirá en un encabezado, excepto en casos especiales, ver a continuación.

Hubo una idea para hacer algo más, el nombre en clave "exportar palabra clave". Fue eliminado del estándar.

Casos especiales: puede compilar instancias de plantilla en un archivo de objeto, sin tener que utilizarlas. Esta es la única forma de evitar tener todo el código de la plantilla en línea. Así es como se hace:

template class std::vector<MyClass>; 

Esto forzará al compilador para crear instancias de una plantilla en la ubicación actual. C++ 0x tendrá una sintaxis para forzar compilador no para hacerlo, y tienen el enlazador de búsqueda de instancias de plantilla en otra parte:

extern template class std::vector<MyClass>; // C++0x only

+4

No está alineado, necesariamente. Se crea una instancia en la unidad de compilación, y puede estar en línea pero no puede. –

+1

La palabra clave export no tiene nada que ver con la inserción, sino que se trata de proporcionar plantillas en forma compilada para una instanciación posterior por código de cliente. –

0

¿Quiere decir instanciado, no compilado. En tiempo de compilación, el compilador descubre todas y cada una de las versiones que utiliza el código e instala (en archivos de objetos) todas las versiones necesarias.

3

Sí, el código de función de la plantilla se emite en el archivo main.o. Algunos de ellos pueden estar en línea, ya que cualquier otro código puede estar en línea, pero en general, el código para plantillas se emite en cualquier archivo en el que la plantilla sea instanciada. Piense en ello como la primera instancia del código de plantilla para producir funciones normales que no sean de plantilla, y luego compila esas funciones con cualquier alineación y optimización que el compilador aplique a cualquier otra función.

Cuando se produce la misma instanciación de plantilla (por ejemplo, std::vector<int>) en varias unidades de compilación (archivos .cpp), hay un poco de dificultad, porque el código se instancia en cada uno de ellos. Hay varias maneras de manejar esto, que a veces implican un paso de limpieza en la fase de vinculación donde las instancias de plantillas duplicadas se resuelven en una sola; su manual del compilador puede brindarle más información sobre cómo maneja exactamente esa situación.

+0

por lo que la creación de una clase de plantilla con una variable ficticia que no se utiliza no es lo mismo que crear una clase y poner todo en el archivo de encabezado. El último estará en línea y la clase de plantilla depende del compilador. ¿Qué hace con eso? – hidayat

+0

@hidayat: No. Las mismas reglas se aplican para las clases "normales" y las plantillas de clase. –

+0

Re duplicados: creo que es una característica estándar de los formatos de archivo de objeto tener una sección que se puede combinar en el momento del enlace. I * think * al menos un sistema los llama secciones 'COMDAT': http://docsun.cites.uiuc.edu/sun_docs/C/solaris_9/SUNWdev/LLM/p44.html (IIRC algunos enlazadores incluso verifican si las secciones son idénticos para detectar algunos errores). – BCS

1

El código de la plantilla es compilado incluso si nunca se ha creado una instancia.De lo contrario, los compiladores no podían ser necesarios para emitir un diagnóstico para esto:

template< typename T > 
void f() 
{ 
    blah 
} 

compilación Plantilla sucede en dos fases. Además de las comprobaciones básicas, todo lo que depende de los parámetros de la plantilla solo se puede verificar cuando se crea una instancia de una plantilla y se completan los parámetros formales con los tipos reales. Por ejemplo, aquí

template< typename T > 
void f() 
{ 
    typename T::nested_type x; 
} 

T::nested_type sólo pueden seleccionarse después de que la plantilla se crea una instancia y se le da un tipo real de T. Sin embargo, una verificación básica ("dado T::nested_type es un tipo, ¿es esta una definición de variable válida?") Se realiza en el momento en que el compilador encuentra la definición de la plantilla. (Por eso se requiere que typename, por cierto Dependiendo de T, T::nested_type podría muy bien ser el nombre del miembro del T o un miembro de datos estáticos -.. Lo que haría T::nested_type x; un error de sintaxis Así que tenemos que decirle al compilador para tratar T::nested_type como el nombre de un tipo.)