名前空間
変種
操作

ソースファイルのインクルード

From cppreference.com
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - 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 - 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つ以上の プリプロセッサートークン。ただし > を除く。

[編集] 説明

1) 実装定義の場所のシーケンスで、h-char-sequence によって一意に識別されるヘッダーを検索し、そのディレクティブをヘッダー全体の内容で置き換えます。場所の指定方法やヘッダーの識別方法は実装定義です。
2) q-char-sequence によって識別されるソースファイル全体の内容で、そのディレクティブを置き換えます。名前付きソースファイルは実装定義の方法で検索されます。この検索がサポートされていない場合、または検索が失敗した場合、ディレクティブは、元のディレクティブから(`>` 文字を含む)同一のシーケンスで、構文 (1) のように再度処理されます。
3) ディレクティブ内の `include` より後のプリプロセッサートークンは、通常のテキストと同様に処理されます(つまり、マクロ名として定義されている各識別子は、その置換トークンリストで置き換えられます)。すべての置換後の結果のディレクティブが、前の2つの形式のいずれにも一致しない場合、動作は未定義です。`<` と `>` のプリプロセッサートークンのペア、または `"` のペアの間にあるプリプロセッサートークンのシーケンスを、単一のヘッダー名プリプロセッサートークンに結合する方法は実装定義です。
4) h-char-sequence または q-char-sequence によって識別されるヘッダーまたはソースファイルは、そのプリプロセッサートークンシーケンスが構文 (3)pp-tokens であるかのように検索されます。ただし、マクロ展開はそれ以上行われません。そのようなディレクティブが `#include` ディレクティブの構文要件を満たさない場合、プログラムは不正な形式となります。 `__has_include` 式は、ソースファイルの検索が成功した場合は 1、検索が失敗した場合は 0 と評価されます。
5) この形式は、構文 (4) が一致しない場合にのみ考慮されます。この場合、プリプロセッサートークンは通常のテキストと同様に処理されます。

ヘッダー名(つまり `<` h-char-sequence `>` または `"` q-char-sequence `"`)によって識別されるヘッダーがインポート可能である場合、`#include` プリプロセッサディレクティブが、代わりに以下の形式の `import` ディレクティブに置き換えられるかどうかは実装定義です。

import header-name ; new-line

(C++20以降)

`__has_include` は、 `#if` および `#elif` の式の中で展開できます。 `#ifdef`、`#ifndef`(C++23以降では `#elifdef`、`#elifndef`)、および `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` も同様の効果で実装しています。これは、同じファイル(ファイルの同一性はOS固有の方法で決定される)が既にインクルードされている場合、そのファイルの処理を無効にします。

q-char-sequence または h-char-sequence でエスケープシーケンスに似た文字シーケンスが現れた場合、実装によってはエラーになったり、エスケープシーケンスに対応する文字として解釈されたり、まったく異なる意味を持つ場合があります。

`__has_include` の結果が 1 であることは、指定された名前のヘッダーまたはソースファイルが存在することのみを意味します。そのヘッダーまたはソースファイルをインクルードした場合にエラーが発生しないことや、有用な内容が含まれることを意味するわけではありません。たとえば、C++14モードとC++17モードの両方をサポートし、C++14モードで `__has_include` を準拠拡張として提供するC++実装では、`__has_include` はC++14モードで 1 になる可能性がありますが、実際には `#include ` でエラーが発生する可能性があります。

[編集]

#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ドキュメント: ソースファイルのインクルード
English 日本語 中文(简体) 中文(繁體)