Tutorial: Importación de bibliotecas STL como unidades de encabezado
En este tutorial, se muestra cómo importar bibliotecas STL (bibliotecas de plantillas estándar) de C++ como unidades de encabezado en Visual Studio. Para obtener una manera aún más rápida y sólida de importar la biblioteca estándar, consulte Tutorial: Importación de la biblioteca estándar de C++ mediante módulos.
Importar un encabezado STL como una unidad de encabezado es más sencillo que usar archivos de encabezado precompilados. Las unidades de encabezado son más fáciles de configurar y usar. Son considerablemente más pequeñas en el disco, proporcionan ventajas de rendimiento similares y son más flexibles que un PCH compartido.
Para obtener información más detallada sobre qué son las unidades de encabezado y las ventajas que proporcionan, consulte ¿Qué es una unidad de encabezado?. Para comparar las unidades de encabezado con otras formas de importar la biblioteca estándar, consulte Comparar unidades de encabezado, módulos y encabezados precompilados.
Requisitos previos
Para usar unidades de encabezado, use Visual Studio 2022 o posterior, o Visual Studio 2019, versión 16.11 o posterior. La opción /std:c++20
(o posterior) es necesaria para usar unidades de encabezado.
Dos enfoques para importar encabezados de STL como unidades de encabezado
Para poder importar un encabezado de STL, debe compilarse en una unidad de encabezado. Una unidad de encabezado es una representación binaria de un archivo de encabezado. Tiene una extensión .ifc
.
El enfoque recomendado es crear una biblioteca estática que contenga las unidades de encabezado compiladas para los encabezados de STL que desea usar. A continuación, haga referencia a esa biblioteca y import
sus unidades de encabezado. Este enfoque puede dar lugar a compilaciones más rápidas y una mejor reutilización. Para probar este enfoque, consulte Enfoque 1: Crear una biblioteca estática de unidades de encabezado de biblioteca STL.
Otro enfoque es hacer que Visual Studio examine los encabezados de STL que usted #include
en el proyecto, compilarlos en unidades de encabezado y import
en lugar de #include
esos encabezados. Este enfoque es útil si tiene un código base grande, ya que no tiene que cambiar el código fuente. Este enfoque es menos flexible que el enfoque de biblioteca estática, ya que no se presta para reutilizar las unidades de encabezado compiladas en otros proyectos. Sin embargo, todavía obtiene la ventaja de rendimiento de importar bibliotecas STL individuales como unidades de encabezado. Para probar este enfoque, consulte Enfoque 2: Examen incluye los encabezados STL que se van a importar.
Enfoque 1: Crear una biblioteca estática de unidades de encabezado de biblioteca STL
La manera recomendada de consumir bibliotecas STL como unidades de encabezado es crear uno o varios proyectos de biblioteca estática. Estos proyectos deben estar formados por las unidades de encabezado de la biblioteca STL que desea usar. A continuación, haga referencia a los proyectos de biblioteca para consumir esas unidades de encabezado STL. Es similar a usar encabezados precompilados compartidos, pero más fácil.
Las unidades de encabezado (y los módulos) compilados en un proyecto de biblioteca estática están disponibles automáticamente para hacer referencia a proyectos porque el sistema de proyectos agrega automáticamente la opción de línea de comandos adecuada /headerUnit
al compilador para que los proyectos de referencia puedan importar las unidades de encabezado.
Este enfoque garantiza que la unidad de encabezado de un encabezado determinado se compile una sola vez. Permite importar algunas o todas las unidades de encabezado, lo que no es posible con un PCH. Puede incluir unidades de encabezado en cualquier orden.
En el ejemplo siguiente, se crea un proyecto de biblioteca estática que consta de las unidades de encabezado <iostream>
y <vector>
. Una vez que se haya compilado la solución, hará referencia a este proyecto de unidad de encabezado compartido desde otro proyecto de C++. En todas partes donde import <iostream>;
o import <vector>;
se encuentra, la unidad de encabezado compilada para esa biblioteca se usa en lugar de traducir el encabezado con el preprocesador. Esto mejora el rendimiento de la compilación, como lo hacen los archivos PCH, cuando el mismo encabezado se incluye en varios archivos. Los archivos que incluyen el encabezado no tendrán que procesarlo una y otra vez. En su lugar, se importa la unidad de encabezado compilada ya procesada.
Para crear una biblioteca estática que contenga las bibliotecas STL <iostream>
y <vector>
, siga estos pasos:
Cree un proyecto de C++ vacío. Asígnele el nombre SharedPrj.
Seleccione Proyecto vacío para C++ en los tipos de proyecto disponibles en la ventana Crear un proyecto:Agregue un nuevo archivo C++ al proyecto. Cambie el contenido del archivo a:
import <iostream>; import <vector>;
Configuración de propiedades del proyecto
Establezca las propiedades del proyecto para compartir las unidades de encabezado de este proyecto:
- En el menú principal de Visual Studio, seleccione Proyecto>Propiedades SharedPrj para abrir el cuadro de diálogo Páginas de propiedades del proyecto:
- Seleccione Todas las configuraciones en la lista desplegable Configuración y, a continuación, seleccione Todas las plataformas en la lista desplegable Plataforma. Esta configuración garantiza que los cambios se apliquen si va a compilar para depurar o liberar.
- En el panel izquierdo del cuadro de diálogo Páginas de propiedades del proyecto, seleccione Propiedades de configuración>General.
- Cambie la opción Tipo de configuración a Biblioteca estática (.lib).
- Cambie Estándar de lenguaje C++ por Estándar ISO C++20 (/std:c++20) (o posterior).
- En el panel izquierdo del cuadro de diálogo Páginas de propiedades del proyecto, seleccione Propiedades de configuración>C/C++>General.
- En la lista desplegable Examinar los orígenes en busca de dependencias de módulo, seleccione Sí. (Esta opción hace que el compilador examine el código de las dependencias que se pueden integrar en unidades de encabezado):
- Elija Aceptar para cerrar el cuadro de diálogo Páginas de propiedades del proyecto. Compile la solución mediante Compilar>Compilar solución en el menú principal.
Referencia a la biblioteca de unidades de encabezado
Para importar <iostream>
y <vector>
como unidades de encabezado desde la biblioteca estática, cree un proyecto que haga referencia a la biblioteca estática de la siguiente manera:
Con la solución actual abierta, en el menú de Visual Studio seleccione Archivo>Agregar>Nuevo proyecto.
En el asistente Crear un nuevo proyecto, seleccione la plantilla Aplicación de consola de C++ y elija Siguiente.
Asigne al nuevo proyecto el nombre Tutorial. Cambie la lista desplegable Solución a Agregar a la solución. Elija Crear para crear el proyecto y agregarlo a la solución.
Cambie el contenido del archivo de origen Walkthrough.cpp de la siguiente manera:
import <iostream>; import <vector>; int main() { std::vector<int> numbers = {0, 1, 2}; std::cout << numbers[1]; }
Las unidades de encabezado requieren la opción /std:c++20
(o posterior). Establezca el estándar de idioma mediante los pasos siguientes:
- En Explorador de soluciones, haga clic con el botón derecho en el proyecto Tutorial y seleccione Propiedades para abrir el cuadro de diálogo Páginas de propiedades del proyecto:
- En el panel izquierdo del cuadro de diálogo de páginas de propiedades del proyecto Tutorial, seleccione Propiedades de configuración>General.
- En la lista desplegable Estándar de lenguaje C++, seleccione Estándar ISO C++20 [/std:c++20] (o posterior).
- Elija Aceptar para cerrar el cuadro de diálogo Páginas de propiedades del proyecto.
En el proyecto Walkthrough, agregue una referencia al proyecto SharedPrj con los siguientes pasos:
- En el proyecto Walkthrough, seleccione el nodo Referencias y, luego, Agregar referencia. Seleccione SharedPrj en la lista de proyectos: Agregar esta referencia hace que el sistema de compilación use las unidades de encabezado compiladas por SharedPrj cada vez que un
import
del proyecto Tutorial coincide con una de las unidades de encabezado compiladas de SharedPrj. - Elija Aceptar para cerrar el cuadro de diálogo Agregar referencia.
- Haga clic con el botón derecho en el proyecto Walkthrough y seleccione Establecer como proyecto de inicio.
- Compile la solución. (Use Compilar>Compilar solución en el menú principal). Ejecútela para ver que genera la salida esperada:
1
La ventaja de este método es que se puede hacer referencia al proyecto de biblioteca estática desde cualquier proyecto para reutilizar las unidades de encabezado que contiene. En este ejemplo, la biblioteca estática contiene las unidades de encabezado <vector>
y <iostream>
.
Puede crear un proyecto de biblioteca estática monolítica que contenga todos los encabezados de STL usados habitualmente que quiere importar desde los distintos proyectos. También puede crear proyectos de bibliotecas compartidas más pequeñas para las distintas agrupaciones de bibliotecas STL que quiere importar como unidades de encabezado. Después, haga referencia a esos proyectos de unidad de encabezado compartidos según sea necesario.
El resultado debería ser un mejor rendimiento de la compilación, dado que la importación de una unidad de encabezado reduce considerablemente el trabajo que debe realizar el compilador.
Cuando use este método con sus propios proyectos, compile el proyecto de biblioteca estática mediante las opciones del compilador que sean compatibles con el proyecto que hace referencia a él. Por ejemplo, los proyectos de STL deben compilarse con la opción del compilador /EHsc
para activar el control de excepciones, al igual que los proyectos que hacen referencia al proyecto de biblioteca estática.
Use /translateInclude
La opción del compilador /translateInclude
(disponible en el cuadro de diálogo Páginas de propiedades del proyecto en C/C++>General>Traducir e incluir en importaciones) le facilita el uso de una biblioteca de unidades de encabezado en proyectos más antiguos que #include
las bibliotecas STL. Hace que no sea necesario cambiar las directivas de #include
a import
en el proyecto, a la vez que le da la ventaja de importar las unidades de encabezado en lugar de incluirlas.
Por ejemplo, si tiene #include <vector>
en el proyecto y hace referencia a una biblioteca estática que contiene una unidad de encabezado para <vector>
, no es necesario cambiar manualmente #include <vector>
a import <vector>;
en el código fuente. En su lugar, el compilador trata automáticamente #include <vector>
como import <vector>;
. Para obtener más información detallada sobre este enfoque, vea Enfoque 2: Examen incluye encabezados STL para importar. No todos los archivos de encabezado de STL se pueden compilar en una unidad de encabezado. El elemento enviado header-units.json
con Visual Studio enumera qué archivos de encabezado de STL se pueden compilar en unidades de encabezado. Un encabezado que se basa en macros para especificar su comportamiento a menudo no se puede compilar en una unidad de encabezado.
Una instrucción #include
que no hace referencia a una unidad de encabezado se trata como #include
normal.
Reutilización de unidades de encabezado entre proyectos
Las unidades de encabezado que haya compilado un proyecto de biblioteca estática estarán disponibles de forma automática para todos los proyectos que hagan referencia directa e indirectamente a él. Hay opciones de configuración del proyecto que permiten seleccionar qué unidades de encabezado deben estar disponibles automáticamente para todos los proyectos que hacen referencia. Las opciones se encuentran en la configuración del proyecto, en Directorios de VC++.
- En Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Propiedades para abrir el cuadro de diálogo Páginas de propiedades del proyecto.
- En el panel izquierdo del cuadro de diálogo, seleccione Propiedades de configuración>Directorios de VC++:
Las siguientes propiedades controlan la visibilidad de las unidades de encabezado en el sistema de compilación:
- Public Include Directories (Directorios de inclusión públicos) especifica los directorios del proyecto para las unidades de encabezado que se deben agregar automáticamente a la ruta de acceso de inclusión en los proyectos de referencia.
- Public C++ Module Directories (Directorios de módulo de C++ públicos) especifica qué directorios del proyecto contienen unidades de encabezado que deben estar disponibles para los proyectos de referencia. Esta propiedad permite que algunas unidades de encabezado sean públicas. Es visible para otros proyectos,así que coloque las unidades de encabezado que desea compartir aquí. Si usa esta configuración, para mayor comodidad, especifique Directorios de inclusión públicos para agregar automáticamente los encabezados públicos a la ruta de acceso de inclusión en los proyectos de referencia.
- All Modules are Public (Todos los módulos son públicos): cuando usa unidades de encabezado compiladas como parte de un proyecto de DLL, los símbolos deben exportarse desde el archivo DLL. Para exportar símbolos de módulo automáticamente, establezca esta propiedad en Sí.
Uso de un archivo de módulo precompilado
Por lo general, la manera más fácil de reutilizar las unidades de encabezado entre soluciones consiste en hacer referencia a un proyecto de unidad de encabezado compartido de cada solución.
Si debe usar una unidad de encabezado compilada y no dispone de su proyecto, puede especificar dónde se encuentra el archivo .ifc
compilado para importarlo en la solución. Para acceder a esta configuración:
- En el menú principal, seleccione Proyecto>Propiedades para abrir el cuadro de diálogo Páginas de propiedades del proyecto.
- En el panel izquierdo del cuadro de diálogo, seleccione Propiedades de configuración>C/C++>General.
- En Dependencias de módulo adicionales, agregue los módulos a la referencia, separados por punto y coma. Este es un ejemplo del formato que se va a usar para Dependencias de módulo adicionales:
ModuleName1=Path\To\ModuleName1.ifc; ModuleName2=Path\To\ModuleName2.ifc
Selección entre varias copias de una unidad de encabezado
Si hace referencia a proyectos que compilan varias unidades de encabezado, ya sea con el mismo nombre o para el mismo archivo de encabezado, debe especificar cuál se va a usar. Es posible que tenga versiones diferentes de la unidad de encabezado compiladas con diferentes configuraciones del compilador, por ejemplo, y debe especificar la que coincida con la configuración del proyecto.
Use la propiedad Dependencias de unidad de encabezado adicionales del proyecto para resolver colisiones especificando qué unidad de encabezado se va a usar. De lo contrario, no es posible predecir cuál se elige.
Para establecer la propiedad Dependencias de unidad de encabezado adicionales:
- En el menú principal, seleccione Proyecto>Propiedades para abrir el cuadro de diálogo Páginas de propiedades del proyecto.
- En el panel izquierdo del cuadro de diálogo, seleccione Propiedades de configuración>C/C++>General.
- Especifique qué módulos o archivos de unidad de encabezado se van a usar en Dependencias de unidad de encabezado adicionales para resolver colisiones. Use este formato para Dependencias de unidad de encabezado adicionales:
Path\To\Header1.h= Path\To\HeaderUnit1.ifc;Path\To\Header2.h= Path\To\ HeaderUnit2.ifc
Importante
Asegúrese de que los proyectos que comparten unidades de encabezado se compilan con opciones de compilación compatibles. Si, al implementar la unidad de encabezado, usa opciones de compilación diferentes de las que usó al crearla, el compilador emitirá advertencias.
Nota:
Para usar unidades de encabezado compiladas como parte de un proyecto de DLL, establezca All Modules are Public (Todos los módulos son públicos) en Sí.
Enfoque 2: El examen incluye los encabezados de STL que se van a importar
Otra manera de importar bibliotecas STL es hacer que Visual Studio examine los encabezados de STL que #include
en el proyecto y compilarlos en unidades de encabezado. A continuación, el compilador importa en lugar de incluir esos encabezados.
Esta opción es conveniente cuando el proyecto incluye muchos archivos de encabezado de STL en muchos archivos o cuando el rendimiento de la compilación no es crítico. Esta opción no garantiza que se compile una sola vez una unidad de encabezado para un encabezado determinado. Sin embargo, resulta útil si tiene un código base grande: no tiene que cambiar el código fuente para aprovechar las ventajas de las unidades de encabezado para muchas de las bibliotecas STL que usa.
Este enfoque es menos flexible que el enfoque de biblioteca estática, ya que no se presta para reutilizar las unidades de encabezado compiladas en otros proyectos. Este enfoque podría no ser adecuado para proyectos más grandes: no garantiza un tiempo de compilación óptimo, ya que todos los orígenes deben examinarse para #include
instrucciones.
No todos los archivos de encabezado se pueden convertir automáticamente en unidades de encabezado. Por ejemplo, los encabezados que dependen de la compilación condicional a través de macros no se deben convertir en unidades de encabezado. Hay una lista de permitidos en forma de archivo header-units.json
para los encabezados de STL que el compilador usa cuando se especifica /translateInclude
. Determina qué encabezados de STL se pueden compilar en unidades de encabezado. El archivo header-units.json
se encuentra en el directorio de instalación de Visual Studio. Por ejemplo, %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.30.30705\include\header-units.json
. Si el archivo de encabezado de STL no está en la lista, se trata como #include
normal en lugar de importarlo como una unidad de encabezado. Otra ventaja del archivo header-units.json
es que impide la duplicación de símbolos en las unidades de encabezado compiladas. Es decir, si la compilación de una unidad de encabezado trae varios encabezados de biblioteca, los símbolos no se duplicarán.
Para probar este enfoque, cree un proyecto que incluya dos bibliotecas STL. A continuación, cambie las propiedades del proyecto para que importe las bibliotecas como unidades de encabezado en lugar de incluirlas, como se describe en la sección siguiente.
Creación de un proyecto de aplicación de consola de C++
Siga estos pasos para crear un proyecto que incluya dos bibliotecas STL: <iostream>
y <vector>
.
En Visual Studio, cree un proyecto de aplicación de consola de C++.
Reemplace el contenido del archivo de código fuente de la manera siguiente:
#include <iostream>; #include <vector>; int main() { std::vector<int> numbers = {0, 1, 2}; std::cout << numbers[1]; }
Establecimiento de las opciones del proyecto y ejecución del proyecto
Los pasos siguientes establecen la opción que hace que el compilador examine los encabezados incluidos para traducirlos en unidades de encabezado. También establecen la opción que hace que el compilador trate #include
como si hubiera escrito import
para los archivos de encabezado que se pueden tratar como unidades de encabezado.
- En el menú principal, seleccione Proyecto>Propiedades para abrir el cuadro de diálogo Páginas de propiedades del proyecto.
- Seleccione Todas las configuraciones en la lista desplegable Configuración y, a continuación, seleccione Todas las plataformas en la lista desplegable Plataforma. Esta configuración garantiza que los cambios se apliquen tanto si va a compilar para depurar como liberar y otras configuraciones.
- En el panel izquierdo del cuadro de diálogo, seleccione Propiedades de configuración>C/C++>General.
- Establezca Scan Sources for Module Dependencies (Examinar los orígenes en busca de dependencias de módulo) en Sí. Esta configuración garantiza que todos los archivos de encabezado compatibles se compilen en unidades de encabezado.
- Establezca Traducir e incluir en importaciones en Sí. Esta configuración compila los archivos de encabezado STL enumerados en el archivo
header-unit.json
como unidades de encabezado y, a continuación, los importa en lugar de usar el preprocesador para#include
. - Elija Aceptar para guardar los cambios y cerrar el cuadro de diálogo Páginas de propiedades del proyecto.
La opción /std:c++20
o posterior es necesaria para usar unidades de encabezado. Para cambiar el estándar del lenguaje C++ usado por el compilador:
- En el menú principal, seleccione Proyecto>Propiedades para abrir el cuadro de diálogo Páginas de propiedades del proyecto.
- Seleccione Todas las configuraciones en la lista desplegable Configuración y, a continuación, seleccione Todas las plataformas en la lista desplegable Plataforma. Esta configuración garantiza que los cambios se apliquen tanto si va a compilar para depurar como liberar y otras configuraciones.
- En el panel izquierdo del cuadro de diálogo Páginas de propiedades del proyecto, seleccione Propiedades de configuración>General.
- En la lista desplegable Estándar de lenguaje C++, seleccione Estándar ISO C++20 (/std:c++20) (o posterior).
- Elija Aceptar para guardar los cambios y cerrar el cuadro de diálogo Páginas de propiedades del proyecto.
- Compile la solución mediante Compilar>Compilar solución en el menú principal.
Ejecute la solución para comprobar que genera la salida esperada: 1
La principal consideración acerca de si debe usar este método es conseguir un equilibrio entre la comodidad y el costo que conlleva examinar todos los archivos para determinar qué archivos de encabezado se compilarán como unidades de encabezado.
Consulte también
Comparación de unidades de encabezado, módulos y encabezados precompilados
Tutorial: Importación de la biblioteca estándar de C++ mediante módulos
Tutorial: Compilación e importación de unidades de encabezado en proyectos de Visual C++
/translateInclude