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

Inclut un autre fichier source dans le fichier source courant à la ligne immédiatement après la directive.

Table des matières

Syntaxe

#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) (depuis C++17)
__has_include ( string-literal )
__has_include ( < h-pp-tokens > )
(5) (depuis C++17)
1) Recherche un en-tête identifié de manière unique par h-char-sequence et remplace la directive par l'intégralité du contenu de l'en-tête.
2) Recherche un fichier source identifié par q-char-sequence et remplace la directive par l'intégralité du contenu du fichier source. Il peut revenir à (1) et traiter q-char-sequence comme un identifiant d'en-tête.
3) Si ni (1) ni (2) ne correspondent, pp-tokens subiront un remplacement de macro. La directive après remplacement sera tentée à nouveau pour correspondre avec (1) ou (2) .
4) Vérifie si un fichier d'en-tête ou de source est disponible pour l'inclusion.
5) Si (4) n'est pas satisfait, h-pp-tokens subira un remplacement de macro. La directive après remplacement sera tentée d'être mise en correspondance avec (4) à nouveau.
new-line - Le caractère de nouvelle ligne
h-char-sequence - Une séquence d'un ou plusieurs h-char s, où l'apparition de l'un des éléments suivants est conditionnellement supportée avec une sémantique définie par l'implémentation :
  • le caractère '
  • le caractère "
  • le caractère \
  • la séquence de caractères //
  • la séquence de caractères /*
h-char - Tout membre du jeu de caractères source (jusqu'à C++23) jeu de caractères de traduction (depuis C++23) sauf le caractère de nouvelle ligne et >
q-char-sequence - Une séquence d'un ou plusieurs q-char s, où l'apparition de l'un des éléments suivants est conditionnellement supportée avec une sémantique définie par l'implémentation :
  • le caractère '
  • le caractère \
  • la séquence de caractères //
  • la séquence de caractères /*
q-char - Tout membre du jeu de caractères source (jusqu'à C++23) jeu de caractères de traduction (depuis C++23) sauf le caractère de nouvelle ligne et "
pp-tokens - Une séquence d'un ou plusieurs jetons de prétraitement
string-literal - Un littéral de chaîne
h-pp-tokens - Une séquence d'un ou plusieurs jetons de prétraitement sauf >

Explication

1) Recherche une séquence d'emplacements pour un en-tête identifié de manière unique par h-char-sequence , et provoque le remplacement de cette directive par l'intégralité du contenu de l'en-tête. La manière dont les emplacements sont spécifiés ou l'en-tête identifié est définie par l'implémentation.
2) Provoque le remplacement de cette directive par l'intégralité du contenu du fichier source identifié par q-char-sequence . Le fichier source nommé est recherché de manière définie par l'implémentation.
Si cette recherche n'est pas prise en charge, ou si la recherche échoue, la directive est retraitée comme si elle utilisait la syntaxe (1) avec la séquence contenue identique (y compris les > caractères, le cas échéant) de la directive originale.
3) Les jetons de prétraitement après include dans la directive sont traités comme dans le texte normal (c'est-à-dire que chaque identifiant actuellement défini comme nom de macro est remplacé par sa liste de remplacement de jetons de prétraitement).
Si la directive résultant après tous les remplacements ne correspond pas à l'une des deux formes précédentes, le comportement est indéfini.
La méthode par laquelle une séquence de jetons de pré-traitement entre un < et un > paire de jetons de pré-traitement ou une paire de " caractères est combinée en un seul jeton de pré-traitement de nom d'en-tête est définie par l'implémentation.
4) L'en-tête ou le fichier source identifié par h-char-sequence ou q-char-sequence est recherché comme si cette séquence de tokens de prétraitement était les pp-tokens dans la syntaxe (3) , sauf qu'aucune expansion de macro supplémentaire n'est effectuée.
  • Si une telle directive ne satisferait pas aux exigences syntaxiques d'une #include directive, le programme est mal formé.
  • Sinon, l'expression __has_include prend la valeur 1 si la recherche du fichier source réussit, et la valeur 0 si la recherche échoue.
5) Ce formulaire n'est considéré que si la syntaxe (4) ne correspond pas, auquel cas les jetons de prétraitement sont traités comme dans un texte normal.

Si l'en-tête identifié par le header-name (c'est-à-dire, < h-char-sequence > ou " q-char-sequence " ) désigne un en-tête importable, il est défini par l'implémentation si la #include directive de préprocesseur est remplacée par une directive d'importation de la forme

import header-name ; new-line

(depuis C++20)

__has_include peut être développé dans l'expression de #if et #elif . Il est traité comme une macro définie par #ifdef , #ifndef , #elifdef , #elifndef (depuis C++23) et defined mais ne peut pas être utilisé ailleurs.

Notes

Les implémentations typiques ne recherchent que les répertoires d'inclusion standard pour la syntaxe (1) . La bibliothèque standard C++ et la bibliothèque standard C sont implicitement incluses dans ces répertoires d'inclusion standard. Les répertoires d'inclusion standard peuvent généralement être contrôlés par l'utilisateur via les options du compilateur.

L'intention de la syntaxe (2) est de rechercher les fichiers qui ne sont pas contrôlés par l'implémentation. Les implémentations typiques recherchent d'abord le répertoire où réside le fichier courant puis reviennent à (1) .

Lorsqu'un fichier est inclus, il est traité par les phases de traduction 1 à 4, ce qui peut inclure, de manière récursive, l'expansion des directives #include imbriquées, jusqu'à une limite d'imbrication définie par l'implémentation. Pour éviter l'inclusion répétée du même fichier et la récursion infinie lorsqu'un fichier s'inclut lui-même, éventuellement de manière transitive, les gardes d'en-tête sont couramment utilisées : l'intégralité de l'en-tête est encapsulée dans

#ifndef FOO_H_INCLUDED /* any name uniquely mapped to file name */
#define FOO_H_INCLUDED
// contenu du fichier se trouve ici
#endif

De nombreux compilateurs implémentent également le non-standard pragma #pragma once avec des effets similaires : il désactive le traitement d'un fichier si le même fichier (où l'identité du fichier est déterminée de manière spécifique au système d'exploitation) a déjà été inclus.

Une séquence de caractères qui ressemble à une séquence d'échappement dans q-char-sequence ou h-char-sequence peut entraîner une erreur, être interprétée comme le caractère correspondant à la séquence d'échappement, ou avoir une signification complètement différente, selon l'implémentation.

Un résultat de __has_include égal à 1 signifie uniquement qu'un en-tête ou fichier source avec le nom spécifié existe. Cela ne signifie pas que l'en-tête ou le fichier source, lorsqu'il est inclus, ne provoquerait pas d'erreur ou contiendrait quelque chose d'utile. Par exemple, sur une implémentation C++ qui prend en charge à la fois les modes C++14 et C++17 (et fournit __has_include dans son mode C++14 comme extension conforme), __has_include ( < optional > ) peut être 1 en mode C++14, mais en réalité #include <optional> peut provoquer une erreur.

Exemple

#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';
}

Sortie :

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

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement tel que publié Comportement correct
CWG 787 C++98 le comportement est indéfini si une séquence d'échappement est
ressemblée dans q-char-sequence ou h-char-sequence
il est conditionnellement pris en charge

Voir aussi

Une liste des fichiers d'en-tête de la bibliothèque standard C++
Documentation C pour Inclusion de fichier source