名稱空間
變體
操作

原始檔包含

來自 cppreference.com
 
 
C++ 語言
表示式
替代表示
字面量
布林字面量 - 整數 - 浮點數
字元 - 字串 - nullptr (C++11)
使用者定義 (C++11)
工具
屬性 (C++11)
型別
typedef 宣告
類型別名宣告 (C++11)
型別轉換
記憶體分配
類特有的函式屬性
explicit (C++11)
static

特殊成員函式
模板
雜項
 
 

在指令之後立即將其他原始檔包含到當前原始檔中。

目錄

[編輯] 語法

#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) (C++17 起)
__has_include ( string-literal )
__has_include ( < h-pp-tokens > )
(5) (C++17 起)
1) 搜尋由 h-char-sequence 唯一標識的標頭檔案,並用標頭檔案的全部內容替換該指令。
2) 搜尋由 q-char-sequence 標識的原始檔,並用原始檔的全部內容替換該指令。它可能會回退到 (1) 並將 q-char-sequence 視為標頭檔案識別符號。
3) 如果 (1)(2) 均未匹配,則 pp-tokens 將進行宏替換。替換後的指令將再次嘗試與 (1)(2) 匹配。
4) 檢查標頭檔案或原始檔是否可包含。
5) 如果 (4) 未匹配,則 h-pp-tokens 將進行宏替換。替換後的指令將再次嘗試與 (4) 匹配。
new-line - 換行符
h-char-sequence - 一個或多個 h-char 序列,其中以下任何字元的出現是條件支援的,其語義是實現定義的
  • 字元 '
  • 字元 "
  • 字元 \
  • 字元序列 //
  • 字元序列 /*
h-char - 除了換行符和 > 之外的 源字元集(C++23 前)翻譯字元集(C++23 起) 的任何成員
q-char-sequence - 一個或多個 q-char 序列,其中以下任何字元的出現是條件支援的,其語義是實現定義的
  • 字元 '
  • 字元 \
  • 字元序列 //
  • 字元序列 /*
q-char - 除了換行符和 " 之外的 源字元集(C++23 前)翻譯字元集(C++23 起) 的任何成員
pp-tokens - 一個或多個 預處理標記 的序列
string-literal - 一個 字串字面量
h-pp-tokens - 除了 > 之外的一個或多個 預處理標記 的序列

[編輯] 解釋

1) 在實現定義的位置序列中搜索由 h-char-sequence 唯一標識的標頭檔案,並用標頭檔案的全部內容替換該指令。位置的指定方式或標頭檔案的標識方式是實現定義的。
2) 用由 q-char-sequence 標識的原始檔的全部內容替換該指令。以實現定義的方式搜尋指定名稱的原始檔。如果不支援此搜尋,或者搜尋失敗,則該指令將重新處理,如同它讀取了語法 (1),幷包含與原始指令相同的序列(包括可能存在的 > 字元)。
3) 指令中 include 後面的預處理標記按正常文字處理(即,當前定義為宏名稱的每個識別符號都替換為其預處理標記的替換列表)。如果所有替換後生成的指令與前兩種形式不匹配,則行為未定義。將一對 < 和 > 預處理標記之間或一對 " 字元之間的預處理標記序列組合成單個頭名稱預處理標記的方法是實現定義的。
4) 搜尋由 h-char-sequenceq-char-sequence 標識的標頭檔案或原始檔,就像該預處理標記序列是語法 (3) 中的 pp-tokens 一樣,但不再執行宏展開。如果此類指令不滿足 #include 指令的語法要求,則程式格式錯誤。如果原始檔搜尋成功,__has_include 表示式的值為 1,如果搜尋失敗,則為 0
5) 僅當語法 (4) 不匹配時才考慮此形式,在這種情況下,預處理標記將像正常文字一樣處理。

如果由 header-name(即 < h-char-sequence >" q-char-sequence ")標識的標頭檔案表示可匯入的標頭檔案,則 #include 預處理指令是否替換為以下形式的 匯入指令 是實現定義的

import header-name ; new-line

(C++20 起)

__has_include 可以在 #if #elif 的表示式中展開。它被 #ifdef #ifndef #elifdef #elifndef(C++23 起)defined 視為已定義的宏,但不能在其他任何地方使用。

[編輯] 注意

典型的實現僅搜尋標準包含目錄以獲取語法 (1)。C++ 標準庫和 C 標準庫隱式包含在這些標準包含目錄中。標準包含目錄通常可以透過編譯器選項由使用者控制。

語法 (2) 的目的是搜尋不受實現控制的檔案。典型的實現首先搜尋當前檔案所在的目錄,然後回退到 (1)

當一個檔案被包含時,它會透過 翻譯階段 1-4 進行處理,其中可能遞迴地包括巢狀的 #include 指令的展開,直到達到實現定義的巢狀限制。為了避免同一檔案的重複包含以及當檔案(可能是傳遞地)包含自身時無限遞迴,通常使用標頭檔案保護:整個標頭檔案被包裝在

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

許多編譯器還實現了非標準的 pragma #pragma once,具有類似的效果:如果同一檔案(檔案身份以作業系統特定方式確定)已被包含,則它會停用對該檔案的處理。

q-char-sequenceh-char-sequence 中類似於轉義序列的字元序列可能會導致錯誤,被解釋為與轉義序列對應的字元,或者具有完全不同的含義,具體取決於實現。

__has_include 的結果為 1 僅表示存在具有指定名稱的標頭檔案或原始檔。這並不意味著當包含標頭檔案或原始檔時不會導致錯誤或包含任何有用的內容。例如,在一個支援 C++14 和 C++17 模式的 C++ 實現上(並在其 C++14 模式下提供 __has_include 作為符合標準的擴充套件),__has_include(<optional>) 在 C++14 模式下可能為 1,但實際上 #include <optional> 可能會導致錯誤。

[編輯] 示例

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

輸出

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

[編輯] 缺陷報告

下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
CWG 787 C++98 如果轉義序列類似於
q-char-sequenceh-char-sequence
它是條件支援的

[編輯] 參閱

C++ 標準庫標頭檔案列表
C 文件 關於 原始檔包含