Source file inclusion
現在のソースファイルに、他のソースファイルをディレクティブの直後の行に挿入します。
目次 |
構文
#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 | - |
1つ以上の
h-char
のシーケンス。以下のいずれかの出現は、実装定義のセマンティクスで条件付きサポートされる:
|
| h-char | - | ソース文字セット (C++23まで) 翻訳文字セット (C++23以降) の任意のメンバー(改行と > を除く) |
| q-char-sequence | - |
1つ以上の
q-char
のシーケンス。以下のいずれかの出現は、実装定義のセマンティクスで条件付きサポートされる:
|
| q-char | - | ソース文字セット (C++23まで) 翻訳文字セット (C++23以降) の任意のメンバー(改行と " を除く) |
| pp-tokens | - | 1つ以上の プリプロセッシングトークン のシーケンス |
| string-literal | - | 文字列リテラル |
| h-pp-tokens | - | 1つ以上の プリプロセッシングトークン のシーケンス( > を除く) |
説明
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 // ファイルの内容がここに記述されます #endif
多くのコンパイラは非標準の pragma #pragma once も同様の効果で実装しています:同じファイル(ファイルの同一性はOS固有の方法で決定される)が既にインクルードされている場合、そのファイルの処理を無効にします。
q-char-sequence または h-char-sequence 内のエスケープシーケンスに類似する文字シーケンスは、実装によっては、エラーとなる場合、エスケープシーケンスに対応する文字として解釈される場合、または全く異なる意味を持つ場合があります。
__has_include
の結果が
1
であることは、指定された名前のヘッダまたはソースファイルが存在することを意味するのみです。これは、そのヘッダやソースファイルがインクルードされた際にエラーが発生しないことや、有用な内容を含んでいることを保証するものではありません。例えば、C++14モードとC++17モードの両方をサポートするC++実装(かつC++14モードで準拠した拡張として
__has_include
を提供する場合)では、C++14モードにおいて
__has_include
(
<
optional
>
)
が
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++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 787 | C++98 |
エスケープシーケンスが
q-char-sequence または h-char-sequence 内に存在する場合の動作は未定義 |
条件付きサポートとなる |
関連項目
| C++標準ライブラリヘッダーファイルの一覧 | |
|
Cドキュメント
for
ソースファイルインクルード
|