the - typename c++




Almacenamiento de definiciones de funciones de plantilla de C++ en un archivo.CPP (8)

¡Hora de una actualización! Cree un archivo en línea (.inl, o probablemente cualquier otro) y simplemente copie todas sus definiciones en él. Asegúrese de agregar la plantilla sobre cada función ( template <typename T, ...> ). Ahora, en lugar de incluir el archivo de encabezado en el archivo en línea, haga lo contrario. Incluya el archivo en línea después de la declaración de su clase ( #include "file.inl" ).

Realmente no sé por qué nadie ha mencionado esto. No veo inconvenientes inmediatos.

Tengo algún código de plantilla que preferiría haber almacenado en un archivo CPP en lugar de en línea en el encabezado. Sé que esto se puede hacer siempre que se sepa qué tipos de plantillas se utilizarán. Por ejemplo:

archivo .h

class foo
{
public:
    template <typename T>
    void do(const T& t);
};

archivo .cpp

template <typename T>
void foo::do(const T& t)
{
    // Do something with t
}

template void foo::do<int>(const int&);
template void foo::do<std::string>(const std::string&);

Tenga en cuenta las dos últimas líneas: la función foo :: do template solo se usa con ints y std :: strings, por lo que esas definiciones significan que la aplicación se vinculará.

Mi pregunta es: ¿es un hack desagradable o funcionará con otros compiladores / enlazadores? Solo estoy usando este código con VS2008 en este momento, pero desearé transferir a otros entornos.


El problema que describe se puede resolver definiendo la plantilla en el encabezado o mediante el enfoque que describió anteriormente.

Recomiendo leer los siguientes puntos de C ++ FAQ Lite :

Entran en muchos detalles sobre estos (y otros) problemas de plantillas.


Este código está bien formado. Solo debe prestar atención a que la definición de la plantilla es visible en el punto de creación de instancias. Para citar el estándar, § 14.7.2.4:

La definición de una plantilla de función no exportada, una plantilla de función miembro no exportada, una función miembro no exportada o un miembro de datos estáticos de una plantilla de clase estará presente en cada unidad de traducción en la que se haya creado una instancia explícita.


Esto debería funcionar bien en todas partes se admiten las plantillas. La creación de instancias explícitas de plantillas es parte del estándar C ++.


Hay, en el último estándar, una palabra clave ( export ) que ayudaría a aliviar este problema, pero no está implementado en ningún compilador del que yo sepa, aparte de Comeau.

Vea las FAQ-lite sobre esto.


No hay nada malo con el ejemplo que has dado. Pero debo decir que creo que no es eficiente almacenar definiciones de funciones en un archivo cpp. Solo entiendo la necesidad de separar la declaración y la definición de la función.

Cuando se usa junto con la creación de instancias de clase explícita, la Biblioteca de verificación de concepto de Boost (BCCL) puede ayudarlo a generar código de función de plantilla en archivos cpp.


Sí, esa es la forma estándar de hacer una especialización explícita de instancias. Como dijo, no puede crear una instancia de esta plantilla con otros tipos.

Edición: corregido basado en el comentario.


Tu ejemplo es correcto pero no muy portátil. También hay una sintaxis ligeramente más limpia que se puede usar (como lo indica @ namespace-sid).

Supongamos que la clase con plantilla es parte de alguna biblioteca que se va a compartir. ¿Deberían compilarse otras versiones de la clase de plantilla? ¿Se supone que el encargado de la biblioteca debe anticipar todos los usos posibles de la clase?

Un enfoque alternativo es una ligera variación en lo que tiene: agregue un tercer archivo que sea el archivo de implementación / creación de instancias de la plantilla.

archivo foo.h

// Standard header file guards omitted

template <typename T>
class foo
{
public:
    void bar(const T& t);
};

archivo foo.cpp

// Always include your headers
#include "foo.h"

template <typename T>
void foo::bar(const T& t)
{
    // Do something with t
}

archivo foo-impl.cpp

// Yes, we include the .cpp file
#include "foo.cpp"
template class foo<int>;

La única advertencia es que debe decirle al compilador que compile foo-impl.cpp lugar de foo.cpp ya que compilar este último no hace nada.

Por supuesto, puede tener varias implementaciones en el tercer archivo o tener múltiples archivos de implementación para cada tipo que quiera usar.

Esto permite mucha más flexibilidad cuando se comparte la clase de plantilla para otros usos.

Esta configuración también reduce los tiempos de compilación para las clases reutilizadas porque no está recompilando el mismo archivo de encabezado en cada unidad de traducción.





templates