2011-05-28 7 views
24

Obviamente, las bibliotecas de plantillas solo deben ser encabezadas, pero para las que no son de plantillas, ¿cuándo debería crearse solo un encabezado?¿Cuándo debería considerar hacer un encabezado de biblioteca solamente?

+2

cuando no le importe exponer su IP. – Nim

+0

@Nim: Es un programa de código abierto bajo la Licencia de software de Boost, así que ciertamente no me importa. :) –

+0

@Billy: Ah, ¿te metiste en Boost? Gratz? : P – Xeo

Respuesta

14

Si cree que su biblioteca que no es de plantilla podría ser solo de encabezado, considere dividirla en dos archivos y luego proporcionar un tercer archivo que incluya tanto el .h como el .cpp (con un protector de inclusión).

Entonces, cualquiera que use su biblioteca en muchas TU diferentes y sospeche que esto podría estar costando mucho tiempo de compilación, puede hacer fácilmente el cambio para probarla.

Una vez que sepa que los usuarios tienen la opción de utilizar la biblioteca, la respuesta probablemente sea "ofrecer esa opción siempre que sea posible". Así que prácticamente en cualquier momento que incluirlo en múltiples TU no violaría la ODR. Por ejemplo, si sus funciones gratuitas no static se refieren a static globales, entonces no tiene suerte, ya que las diferentes definiciones de esa función en diferentes TU se referirían a objetos diferentes con el mismo nombre, que es una violación ODR.

+2

Oooh. Nunca pensé en hacerlo de esta manera. +1 ¿Cómo se consigue que las declaraciones de función se establezcan en 'en línea' correctamente cuando' .cpp' es '# include'd? –

+2

@Billy: Establezca un '# define' en el tercer archivo (segundo .h), y en .cpp tenga un' #ifdef _____ #define DO_INLINE en línea #else #define DO_INLINE # endif'. – Xeo

+1

O simplemente márcalos 'en línea' siempre, no hace ningún daño. –

-2

Sin plantillas, tendría definiciones reales en los encabezados. Eso significa que si dos archivos incluyen su encabezado, obtendrá múltiples definiciones y el código no se compilará.

En otras palabras, poner definiciones en los encabezados es una muy mala idea. Debes apegarte solo a las declaraciones y a las plantillas.

En cuanto a las plantillas, los compiladores saben que puede incluir el mismo encabezado más de una vez, ya que no generarán el mismo código una y otra vez.

EDITAR: Si quieres decir "mantener todo en línea", creo que este es un enfoque muy malo. Los archivos de cabecera se vuelven completamente ilegibles, y cualquier cambio en la implementación obliga a cualquier usuario de su biblioteca a recompilar todo.

+0

-1: Esto no es verdad. Puede poner definiciones en los encabezados siempre que tengan un enlace interno. (por ejemplo, están declarados 'en línea') –

+0

' inline'. 'dijo nuff. – Xeo

+0

A veces, la necesidad de volver a compilar para cada cambio no es una limitación. –

0

Las bibliotecas de plantillas no necesitan ser solo de encabezado: las implementaciones pueden contener algunas piezas independientes de los parámetros de plantilla, y por alguna razón (por ejemplo, menos tamaño de código) separadas en un binario especial.

No puedo imaginarme un caso en el que una biblioteca que no sea una plantilla realmente deba ser solo de encabezado. Sin embargo, a veces puede ser razonable para el rendimiento permitir la incorporación de todo el código. Un ejemplo puede ser una biblioteca de envoltorios alrededor de interfaces específicas de la plataforma, p. para cosas como primitivas de sincronización, almacenamiento local de subprocesos, implementación específica de plataformas y compiladores de operaciones atómicas, etc.

+0

Alexey: Muéstrame una biblioteca del archivo STL que sea ** no ** solo de encabezado. Y con STL, me refiero a la parte contenedor/algoritmos/iteradores, no a toda la biblioteca estándar. – Xeo

+0

Quizás, pero las partes de plantilla de las bibliotecas de plantillas deben ser solo encabezado. Debe existir una definición de plantilla en la unidad de traducción para que el compilador pueda crear una instancia. Algunos STL tienen partes binarias principalmente porque o bien A. se incluyen como parte de un tiempo de ejecución general de C++ que tiene piezas que no son de plantilla (por ejemplo, 'libstdcxx'), o B. contienen componentes que no son plantillas. En cuanto a la performance, la mayoría de los compiladores tienen hoy en día la generación de código de tiempo de enlace, lo que prácticamente elimina la diferencia de rendimiento entre los dos para compilaciones de lanzamiento. –

+0

@Xeo: bien, probablemente sea correcto, STL no es lo mismo que la biblioteca de soporte de idioma. –

3

Puede seguir el cable de Boost.Asio.

Proporcionan simplemente las dos versiones de las bibliotecas: encabezado solo y encabezado + biblioteca.

Lo hacen con una sola macro que se definirá (o no) antes de incluir sus encabezados. Creo que el valor predeterminado (si no está definido) es usar la versión de solo encabezado.

Ver Optional Separate Compilation.

Tenga en cuenta cómo proporcionan cuidadosamente un único archivo fuente que se compilará que define todo o la opción de vincular con una biblioteca cargada dinámicamente.

Cuestiones relacionadas