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

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)
1) Sucht nach einem Header, der eindeutig durch h-char-sequence identifiziert wird, und ersetzt die Direktive durch den gesamten Inhalt des Headers.
2) Such nach einer Quelldatei, identifiziert durch q-char-sequence und ersetzt die Direktive durch den gesamten Inhalt der Quelldatei. Es kann auf (1) zurückgreifen und q-char-sequence als Header-Identifikator behandeln.
3) Wenn weder (1) noch (2) zutrifft, werden pp-tokens einer Makroersetzung unterzogen. Die Anweisung wird nach der Ersetzung erneut versucht, mit (1) oder (2) abgeglichen zu werden.
4) Prüft, ob eine Header- oder Quelldatei zur Einbindung verfügbar ist.
5) Wenn (4) nicht übereinstimmt, werden h-pp-tokens einer Makroersetzung unterzogen. Die Anweisung nach der Ersetzung wird erneut versucht, mit (4) abgeglichen zu werden.
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:
  • das Zeichen '
  • das Zeichen "
  • das Zeichen \
  • die Zeichensequenz //
  • die Zeichensequenz /*
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:
  • das Zeichen '
  • das Zeichen \
  • die Zeichensequenz //
  • die Zeichensequenz /*
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

1) Durchsucht eine Folge von Orten nach einem Header, der eindeutig durch h-char-sequence  identifiziert wird, und bewirkt den Ersatz dieser Direktive durch den gesamten Inhalt des Headers. Wie die Orte spezifiziert oder der Header identifiziert wird, ist implementierungsdefiniert.
2) Führt zum Ersetzen dieser Direktive durch den gesamten Inhalt der durch q-char-sequence  identifizierten Quelldatei. Die benannte Quelldatei wird auf implementierungsdefinierte Weise gesucht.
Wenn diese Suche nicht unterstützt wird oder fehlschlägt, wird die Direktive erneut verarbeitet, als ob sie die Syntax (1) mit der identischen enthaltenen Sequenz (einschließlich > Zeichen, falls vorhanden) aus der ursprünglichen Direktive verwendet.
3) Die Präprozessor-Tokens nach 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 die Direktive nach allen Ersetzungen nicht einer der beiden vorherigen Formen entspricht, ist das Verhalten undefiniert.
Die Methode, durch die eine Sequenz von Präprozessor-Tokens zwischen einem < und einem > Präprozessor-Token-Paar oder einem Paar von " Zeichen zu einem einzelnen Header-Name-Präprozessor-Token kombiniert wird, ist implementierungsdefiniert.
4) Die Header- oder Quelldatei, die durch h-char-sequence oder q-char-sequence identifiziert wird, wird so durchsucht, als ob diese Präprozessor-Token-Sequenz die pp-tokens in Syntax (3) wäre, mit der Ausnahme, dass keine weitere Makroexpansion durchgeführt wird.
  • 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.
5) Diese Form wird nur berücksichtigt, wenn die Syntax (4) nicht übereinstimmt, in welchem Fall die Präprozessor-Tokens genauso wie in normalem Text verarbeitet werden.

Wenn die durch den header-name identifizierte Header-Datei (d.h. < h-char-sequence > oder " q-char-sequence " ) einen importierbaren Header bezeichnet, ist implementierungsdefiniert, ob die #include Präprozessor-Direktive stattdessen durch eine Import-Direktive der Form ersetzt wird

import header-name ; new-line

(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