Namespaces
Variants

Source file inclusion

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Incluye otro archivo fuente en el archivo fuente actual en la línea inmediatamente posterior a la directiva.

Contenidos

Sintaxis

#include < h-char-sequence > new-line (1)
#include " q-char-sequence " new-line (2)
#include pp-tokens new-line (3)
__has_include ( " q-char-sequence " )
__has_include ( < h-char-sequence > )
(4) (desde C++17)
__has_include ( string-literal )
__has_include ( < h-pp-tokens > )
(5) (desde C++17)
1) Busca un encabezado identificado únicamente por h-char-sequence y reemplaza la directiva por el contenido completo del encabezado.
2) Busca un archivo fuente identificado por q-char-sequence y reemplaza la directiva por el contenido completo del archivo fuente. Puede recurrir a (1) y tratar q-char-sequence como un identificador de cabecera.
3) Si ni (1) ni (2) coinciden, pp-tokens sufrirán reemplazo de macro. La directiva después del reemplazo se intentará hacer coincidir con (1) o (2) nuevamente.
4) Verifica si un archivo de cabecera o fuente está disponible para inclusión.
5) Si (4) no coincide, h-pp-tokens sufrirá reemplazo de macro. La directiva después del reemplazo se intentará hacer coincidir con (4) nuevamente.
new-line - El carácter de nueva línea
h-char-sequence - Una secuencia de uno o más h-char s, donde la aparición de cualquiera de los siguientes es condicionalmente compatible con semántica definida por la implementación:
  • el carácter '
  • el carácter "
  • el carácter \
  • la secuencia de caracteres //
  • la secuencia de caracteres /*
h-char - Cualquier miembro del juego de caracteres fuente (hasta C++23) juego de caracteres de traducción (desde C++23) excepto nueva línea y >
q-char-sequence - Una secuencia de uno o más q-char s, donde la aparición de cualquiera de los siguientes es condicionalmente compatible con semántica definida por la implementación:
  • el carácter '
  • el carácter \
  • la secuencia de caracteres //
  • la secuencia de caracteres /*
q-char - Cualquier miembro del juego de caracteres fuente (hasta C++23) juego de caracteres de traducción (desde C++23) excepto nueva línea y "
pp-tokens - Una secuencia de uno o más tokens de preprocesamiento
string-literal - Un literal de cadena
h-pp-tokens - Una secuencia de uno o más tokens de preprocesamiento excepto >

Explicación

1) Busca una secuencia de lugares para un encabezado identificado unívocamente por h-char-sequence , y provoca el reemplazo de esa directiva por el contenido completo del encabezado. Cómo se especifican los lugares o se identifica el encabezado está definido por la implementación.
2) Provoca que la directiva sea reemplazada por el contenido completo del archivo fuente identificado por q-char-sequence . El archivo fuente nombrado se busca de una manera definida por la implementación.
Si esta búsqueda no es compatible, o si la búsqueda falla, la directiva se reprocesa como si leyera sintaxis (1) con la secuencia contenida idéntica (incluyendo > caracteres, si los hay) de la directiva original.
3) Los tokens de preprocesamiento después de include en la directiva se procesan exactamente como en texto normal (es decir, cada identificador actualmente definido como nombre de macro se reemplaza por su lista de reemplazo de tokens de preprocesamiento).
Si la directiva resultante después de todas las sustituciones no coincide con una de las dos formas anteriores, el comportamiento es indefinido.
El método mediante el cual una secuencia de tokens de preprocesamiento entre un < y un > par de tokens de preprocesamiento o un par de caracteres " se combina en un único token de preprocesamiento de nombre de cabecera está definido por la implementación.
4) El archivo de cabecera o fuente identificado por h-char-sequence o q-char-sequence se busca como si esa secuencia de tokens de preprocesamiento fueran los pp-tokens en la sintaxis (3) , excepto que no se realiza ninguna expansión de macros adicional.
  • Si dicha directiva no satisficiera los requisitos sintácticos de una #include directive, el programa está mal formado.
  • De lo contrario, la expresión __has_include se evalúa como 1 si la búsqueda del archivo fuente tiene éxito, y como 0 si la búsqueda falla.
5) Esta forma se considera solo si la sintaxis (4) no coincide, en cuyo caso los tokens de preprocesamiento se procesan igual que en el texto normal.

Si el encabezado identificado por el header-name (es decir, < h-char-sequence > o " q-char-sequence " ) denota un encabezado importable, está definido por la implementación si la #include directiva de preprocesamiento es reemplazada en su lugar por una directiva import de la forma

import header-name ; new-line

(since C++20)

__has_include puede expandirse en la expresión de #if y #elif . Es tratado como una macro definida por #ifdef , #ifndef , #elifdef , #elifndef (desde C++23) y defined pero no puede utilizarse en ningún otro lugar.

Notas

Las implementaciones típicas solo buscan en los directorios de inclusión estándar para la sintaxis (1) . La biblioteca estándar de C++ y la biblioteca estándar de C están implícitamente incluidas en estos directorios de inclusión estándar. Los directorios de inclusión estándar normalmente pueden ser controlados por el usuario mediante opciones del compilador.

La intención de la sintaxis (2) es buscar los archivos que no están controlados por la implementación. Las implementaciones típicas primero buscan en el directorio donde reside el archivo actual y luego recurren a (1) .

Cuando un archivo es incluido, es procesado por las fases de traducción 1-4, lo que puede incluir, recursivamente, la expansión de las directivas anidadas #include , hasta un límite de anidamiento definido por la implementación. Para evitar la inclusión repetida del mismo archivo y la recursión infinita cuando un archivo se incluye a sí mismo, quizás de forma transitiva, comúnmente se utilizan guardas de cabecera : todo el encabezado se envuelve en

#ifndef FOO_H_INCLUDED /* any name uniquely mapped to file name */
#define FOO_H_INCLUDED
// contents of the file are here
#endif

Muchos compiladores también implementan la no estándar pragma #pragma once con efectos similares: desactiva el procesamiento de un archivo si el mismo archivo (donde la identidad del archivo se determina de forma específica del sistema operativo) ya ha sido incluido.

Una secuencia de caracteres que se asemeje a una secuencia de escape en q-char-sequence o h-char-sequence podría resultar en un error, ser interpretada como el carácter correspondiente a la secuencia de escape, o tener un significado completamente diferente, dependiendo de la implementación.

Un resultado de __has_include de 1 solo significa que existe un archivo de cabecera o fuente con el nombre especificado. No significa que el archivo de cabecera o fuente, al ser incluido, no causaría un error o contendría algo útil. Por ejemplo, en una implementación de C++ que admite tanto el modo C++14 como C++17 (y proporciona __has_include en su modo C++14 como una extensión conforme), __has_include ( < optional > ) puede ser 1 en modo C++14, pero en realidad #include <optional> puede causar un error.

Ejemplo

#if __has_include(<optional>)
    #include <optional>
    #define has_optional 1
    template<class T>
    using optional_t = std::optional<T>;
#elif __has_include(<experimental/optional>)
    #include <experimental/optional>
    #define has_optional -1
    template<class T>
    using optional_t = std::experimental::optional<T>;
#else
    #define has_optional 0
    template<class V>
    class optional_t
    {
        V v{};
        bool has{};
    public:
        optional_t() = default;
        optional_t(V&& v) : v(v), has{true} {}
        V value_or(V&& alt) const&
        {
            return has ? v : alt;
        }
        // etc.
    };
#endif
#include <iostream>
int main()
{
    if (has_optional > 0)
        std::cout << "<optional> is present\n";
    else if (has_optional < 0)
        std::cout << "<experimental/optional> is present\n";
    else
        std::cout << "<optional> is not present\n";
    optional_t<int> op;
    std::cout << "op = " << op.value_or(-1) << '\n';
    op = 42;
    std::cout << "op = " << op.value_or(-1) << '\n';
}

Salida:

<optional> is present
op = -1
op = 42

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 787 C++98 el comportamiento es indefinido si una secuencia de escape
se asemeja en q-char-sequence o h-char-sequence
es condicionalmente soportado

Véase también

Una lista de archivos de cabecera de la Biblioteca Estándar de C++
Documentación de C para Inclusión de archivos fuente