原始檔包含
在指令之後立即將其他原始檔包含到當前原始檔中。
目錄 |
[編輯] 語法
#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 起) | |||||||
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 | - | 除了 > 之外的一個或多個 預處理標記 的序列 |
[編輯] 解釋
include
後面的預處理標記按正常文字處理(即,當前定義為宏名稱的每個識別符號都替換為其預處理標記的替換列表)。如果所有替換後生成的指令與前兩種形式不匹配,則行為未定義。將一對 < 和 > 預處理標記之間或一對 " 字元之間的預處理標記序列組合成單個頭名稱預處理標記的方法是實現定義的。#include
指令的語法要求,則程式格式錯誤。如果原始檔搜尋成功,__has_include
表示式的值為 1,如果搜尋失敗,則為 0。
如果由 header-name(即
|
(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-sequence 或 h-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-sequence 或 h-char-sequence 中 |
它是條件支援的 |
[編輯] 參閱
C++ 標準庫標頭檔案列表 | |
C 文件 關於 原始檔包含
|