Source file inclusion
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) | |||||||
| 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 :
|
| 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 :
|
| 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
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 une telle directive ne satisferait pas aux exigences syntaxiques d'une #include directive, le programme est mal formé.
-
Sinon, l'expression
__has_includeprend la valeur 1 si la recherche du fichier source réussit, et la valeur 0 si la recherche échoue.
|
Si l'en-tête identifié par le
header-name
(c'est-à-dire,
|
(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
|