Source file inclusion
Bindet andere Quelldateien in die aktuelle Quelldatei in der Zeile unmittelbar nach der Direktive ein.
Inhaltsverzeichnis |
Syntax
#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) | (seit C++17) | |||||||
__has_include
(
string-literal
)
__has_include
(
<
h-pp-tokens
>
)
|
(5) | (seit C++17) | |||||||
| new-line | - | Das Zeilenumbruchzeichen |
| h-char-sequence | - |
Eine Sequenz von einem oder mehreren
h-char
s, wobei das Auftreten eines der folgenden Zeichen bedingt unterstützt wird mit implementierungsdefinierter Semantik:
|
| h-char | - | Jedes Mitglied des Quellzeichensatzes (bis C++23) Übersetzungszeichensatzes (seit C++23) außer Zeilenumbruch und > |
| q-char-sequence | - |
Eine Sequenz von einem oder mehreren
q-char
s, wobei das Auftreten eines der folgenden Zeichen bedingt unterstützt wird mit implementierungsdefinierter Semantik:
|
| q-char | - | Jedes Mitglied des Quellzeichensatzes (bis C++23) Übersetzungszeichensatzes (seit C++23) außer Zeilenumbruch und " |
| pp-tokens | - | Eine Sequenz von einem oder mehreren Präprozessor-Tokens |
| string-literal | - | Ein Zeichenkettenliteral |
| h-pp-tokens | - | Eine Sequenz von einem oder mehreren Präprozessor-Tokens außer > |
Erklärung
include
in der Direktive werden genauso verarbeitet wie in normalem Text (d.h., jeder als Makroname definierte Bezeichner wird durch seine Ersetzungsliste von Präprozessor-Tokens ersetzt).
- Wenn eine solche Direktive die syntaktischen Anforderungen einer #include -Direktive nicht erfüllen würde, ist das Programm fehlerhaft.
-
Andernfalls ergibt der
__has_include-Ausdruck 1 , wenn die Suche nach der Quelldatei erfolgreich ist, und 0 , wenn die Suche fehlschlägt.
|
Wenn die durch den
header-name
identifizierte Header-Datei (d.h.
|
(since C++20) |
__has_include
kann in den Ausdrücken von
#if
und
#elif
expandiert werden. Es wird als definiertes Makro behandelt von
#ifdef
,
#ifndef
,
#elifdef
,
#elifndef
(seit C++23)
und
defined
, kann aber nirgendwo anders verwendet werden.
Hinweise
Typische Implementierungen durchsuchen nur Standard-Includeverzeichnisse nach Syntax (1) . Die Standard-C++-Bibliothek und die Standard-C-Bibliothek sind implizit in diesen Standard-Includeverzeichnissen enthalten. Die Standard-Includeverzeichnisse können normalerweise durch den Benutzer über Compiler-Optionen gesteuert werden.
Die Absicht der Syntax (2) ist es, nach Dateien zu suchen, die nicht durch die Implementierung kontrolliert werden. Typische Implementierungen durchsuchen zuerst das Verzeichnis, in dem die aktuelle Datei sich befindet, und greifen dann auf (1) zurück.
Wenn eine Datei eingebunden wird, wird sie durch die Übersetzungsphasen 1-4 verarbeitet, was rekursiv die Expansion von verschachtelten #include -Direktiven einschließen kann, bis zu einem implementierungsdefinierten Verschachtelungslimit. Um wiederholtes Einbinden derselben Datei und Endlosrekursion zu vermeiden, wenn eine Datei sich selbst (möglicherweise transitiv) einbindet, werden üblicherweise Header Guards verwendet: Der gesamte Header wird eingewickelt in
#ifndef FOO_H_INCLUDED /* any name uniquely mapped to file name */ #define FOO_H_INCLUDED // Inhalt der Datei befindet sich hier #endif
Viele Compiler implementieren auch das nicht-standardisierte pragma #pragma once mit ähnlicher Wirkung: Es deaktiviert die Verarbeitung einer Datei, falls dieselbe Datei (wobei die Dateiidentität auf betriebssystemspezifische Weise bestimmt wird) bereits eingebunden wurde.
Eine Zeichenfolge, die einer Escape-Sequenz in q-char-sequence oder h-char-sequence ähnelt, kann je nach Implementierung zu einem Fehler führen, als das der Escape-Sequenz entsprechende Zeichen interpretiert werden oder eine völlig andere Bedeutung haben.
Ein
__has_include
-Ergebnis von
1
bedeutet lediglich, dass eine Header- oder Quelldatei mit dem angegebenen Namen existiert. Es bedeutet nicht, dass die Header- oder Quelldatei, wenn sie eingebunden wird, keinen Fehler verursachen würde oder etwas Nützliches enthalten würde. Beispielsweise könnte bei einer C++-Implementierung, die sowohl den C++14- als auch den C++17-Modus unterstützt (und
__has_include
in ihrem C++14-Modus als konforme Erweiterung bereitstellt),
__has_include
(
<
optional
>
)
im C++14-Modus
1
sein, aber tatsächlich könnte
#include <optional>
einen Fehler verursachen.
Beispiel
#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'; }
Ausgabe:
<optional> is present op = -1 op = 42
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| CWG 787 | C++98 |
das Verhalten ist undefiniert, wenn ein Escape-Sequenz
in q-char-sequence oder h-char-sequence ähnelt |
es ist bedingt unterstützt |
Siehe auch
| Eine Liste von C++ Standardbibliothek-Headerdateien | |
|
C-Dokumentation
für
Quelltextdatei-Einbindung
|