2011-09-08 13 views
8

Estamos en el proceso de diseñar una nueva biblioteca de C++ y decidimos utilizar un enfoque basado en plantillas junto con algunas especializaciones de plantillas parciales específicas para casos de esquina. En particular, esta será una biblioteca de plantillas de solo encabezado .¿Compila la biblioteca de plantillas solo de encabezado en una biblioteca compartida?

Ahora, existe la preocupación de que esto conducirá a una gran cantidad de duplicación de código en los binarios, ya que esta plantilla 'biblioteca' se compila en cualquier otra biblioteca compartida o ejecutable que lo utiliza (podría decirse que sólo aquellas partes que se usan). Todavía creo que esto no es un problema (en particular, el compilador incluso podría alinear cosas que no podría en los límites compartidos de la biblioteca).

Sin embargo, dado que conocemos el conjunto finito de tipos para el que se va a utilizar, ¿hay alguna forma de compilar este encabezado en una biblioteca y proporcionar un encabezado diferente con solo las declaraciones y nada más? Tenga en cuenta que la biblioteca debe contener no solo las implementaciones genéricas, sino también las especializaciones parciales ..

+0

¿Te refieres a "finito" o "acotado"? Obviamente, cualquier cosa que hagas en una computadora, o en este universo, va a ser finita, por lo que la distinción es crucial. –

+0

Quise decir limitado: necesitaremos instancias de estas plantillas para unos 8 tipos y nada más. Entonces podríamos escribir fácilmente una lista. – lytenyn

+0

Hmm, no estoy del todo seguro, y seguramente tendrá que enviar los encabezados reales, pero podría agregar instancias explícitas para esos tipos a un archivo fuente y compilar eso y declarar esas plantillas 'extern' en cualquier otro lugar. Nunca lo intenté, pero creo que se supone que tiene el efecto deseado. –

Respuesta

6

Sí. Lo que puede hacer es crear instancias explícitas de las plantillas en archivos CPP utilizando la sintaxis de instanciación de plantilla explícita del compilador. Aquí se muestra cómo usar la creación de instancias explícita en VC++: http://msdn.microsoft.com/en-us/library/by56e477(v=VS.100).aspx. G ++ tiene una característica similar: http://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html#Template-Instantiation.

Obsérvese que C++ 11 introdujo una sintaxis estándar para instanciación explícita, se describe en [14.7.2] instanciación explícita de la FDIS:

La sintaxis para instanciación explícita es:

explícita de instancias:

externopttemplatedeclaración

+1

Gracias, esta publicación también fue muy útil: http://anteru.net/2008/11/19/318/ – lytenyn

1

Si es realmente solo una plantilla, no hay una biblioteca compartida. Vea varios proyectos Boost para ejemplos concretos. Solo cuando tenga código que no sea de plantilla tendrá una biblioteca. Un ejemplo concreto es, por ejemplo, Boost Date_Time y el formato y el análisis de fechas; puede usar la biblioteca con o sin esa característica y, por lo tanto, con o sin enlace.

No tener una biblioteca compartida es bueno en el sentido de tener menos dependencias. La desventaja es que sus binarios pueden ser un poco más grandes y que tiene costos de tiempo de compilación algo más altos. Pero el almacenamiento es bastante barato (a menos que trabaje en sistemas integrados son otras circunstancias especiales) y compilar es generalmente un costo fijo de una sola vez.

3

C++ Shared Library with Templates: Undefined symbols error Algunas respuestas abordan este tema. En resumen: es posible si fuerza la creación de instancias de plantillas en código de biblioteca compartida explícitamente. Sin embargo, requerirá una especificación explícita para todos los tipos utilizados para todas las plantillas utilizadas en el lado de la lib compartido.

0

Aunque no hay una forma estándar de hacerlo, por lo general es posible con las técnicas específicas de implementación. Lo hice hace mucho tiempo con el C++ Builder de Borland. La idea es declarar sus plantillas para exportar desde la biblioteca compartida donde necesitan residir e importarlas donde se usan.La forma en que lo hice fue a lo largo de estas líneas:

// A.h 
#ifdef GENERATE 
# define DECL __declspec(dllexport) 
#else 
# define DECL __declspec(dllimport) 
#endif 

template <typename T> class DECL C { 
}; 

// A.cpp 
#define GENERATE 
#include "A.h" 

template class DECL A<int>; 

Tenga en cuenta que no tengo acceso al código original, por lo que pueden contener errores. This blog entry describe un enfoque muy similar.

Según su redacción, sospecho que no está en Windows, por lo que deberá averiguar si este compilador puede adoptar este enfoque y cómo hacerlo. Espero que esto sea suficiente para ponerte en la dirección correcta.

Cuestiones relacionadas