すべての回答とコンパイラのドキュメントを読んだ後、次の標準に従うことにしました。
プロジェクトヘッダーまたは外部ヘッダーであるすべてのファイルに対して、常に次のパターンを使用します。
#include <namespace/header.hpp>
衝突を避けるために、名前空間は少なくとも 1 つのディレクトリの深さになります。
もちろん、これは、プロジェクト ヘッダーが配置されているプロジェクト ディレクトリを「デフォルトのインクルード ヘッダー」としてメイクファイルにも追加する必要があることを意味します。
この選択の理由は、次の情報を見つけたからです。
1. インクルード "" パターンはコンパイラに依存します
私は以下の答えを与えます
1.a 標準
ソース:
セクション 16.2 ソース ファイル インクルードでは、次のことがわかります。
フォームの前処理ディレクティブ
#include <h-char-sequence> new-line
< と > 区切り文字の間の指定されたシーケンスによって一意に識別されるヘッダーの実装定義の場所のシーケンスを検索し、そのディレクティブをヘッダーの内容全体で置き換えます。場所を指定する方法またはヘッダーを識別する方法は実装定義です。
これは、 #include <...> が実装定義の方法でファイルを検索することを意味します。
次に、次の段落:
フォームの前処理ディレクティブ
#include "q-char-sequence" new-line
このディレクティブは、" デリミタ間の指定されたシーケンスで識別されるソース ファイルの内容全体に置き換えられます。指定されたソース ファイルは、実装定義の方法で検索されます。この検索がサポートされていない場合、または検索が失敗した場合は、 、ディレクティブは読み取ったかのように再処理されます
#include <h-char-sequence> new-line
元のディレクティブからの同一の含まれるシーケンス (存在する場合は > 文字を含む) を使用します。
これは、#include "..." が実装定義の方法でファイルを検索し、ファイルが見つからない場合、#include <...> であるかのように別の検索を行うことを意味します。
結論は、コンパイラのドキュメントを読む必要があるということです。
何らかの理由で、標準のどこにも「システム」または「ライブラリ」ヘッダーまたはその他のヘッダーの違いがないことに注意してください。唯一の違いは、#include <...> はヘッダーをターゲットにしているように見えますが、#include "..." はソースをターゲットにしているようです (少なくとも、英語の表現では)。
1.b ビジュアル C++:
ソース:
#include "MyFile.hpp"
プリプロセッサは、次の順序でインクルード ファイルを検索します。
- #include ステートメントを含むファイルと同じディレクトリ。
- 以前に開いたインクルード ファイルのディレクトリで、開いたときと逆の順序で。検索は、最後に開かれたインクルード ファイルのディレクトリから開始され、最初に開かれたインクルード ファイルのディレクトリまで続きます。
- 各 /I コンパイラ オプションで指定されたパスに沿って。
- (*) INCLUDE 環境変数または開発環境のデフォルト インクルードで指定されたパスに沿って。
#include <MyFile.hpp>
プリプロセッサは、次の順序でインクルード ファイルを検索します。
- 各 /I コンパイラ オプションで指定されたパスに沿って。
- (*) INCLUDE 環境変数または開発環境のデフォルト インクルードで指定されたパスに沿って。
最後のステップについての注意
ドキュメントは、 と include の両方の「INCLUDE 環境変数で指定されたパスに沿って」部分について明確ではありませ<...>
ん"..."
。次の引用により、標準に準拠しています。
#include "path-spec" として指定されたインクルード ファイルの場合、ディレクトリ検索は親ファイルのディレクトリから開始され、次にすべての親の親ファイルのディレクトリに進みます。つまり、検索は、処理中の #include ディレクティブを含むソース ファイルを含むディレクトリに対して相対的に開始されます。祖父母ファイルがなく、ファイルが見つからない場合は、ファイル名が山かっこで囲まれているかのように検索が続行されます。
したがって、最後のステップ (アスタリスクでマークされている) は、ドキュメント全体を読んだ結果の解釈です。
1.cg++
ソース:
次の引用は、プロセスを要約しています。
GCC [...] は #include<file>
で要求されたヘッダーを [システム ディレクトリ] で検索します [...] -I で指定されたすべてのディレクトリは、デフォルト ディレクトリの前に左から右の順序で検索されます
GCC は #include "file" で要求されたヘッダーを最初に現在のファイルを含むディレクトリで検索し、次に -iquote オプションで指定されたディレクトリで検索します。次に、山かっこで要求されたヘッダーを検索した場合と同じ場所で検索します。
#include "MyFile.hpp"
このバリアントは、独自のプログラムのヘッダー ファイルに使用されます。プリプロセッサは、次の順序でインクルード ファイルを検索します。
- #include ステートメントを含むファイルと同じディレクトリ。
- 各 -iquote コンパイラ オプションで指定されたパスに沿って。
- #include について
<MyFile.hpp>
#include <MyFile.hpp>
このバリアントは、システム ヘッダー ファイルに使用されます。プリプロセッサは、次の順序でインクルード ファイルを検索します。
- 各 -I コンパイラ オプションで指定されたパスに沿って。
- システムディレクトリ内。
1.d Oracle/Sun Studio CC
ソース:
テキスト自体が多少矛盾していることに注意してください (理解するには例を参照してください)。キー フレーズは次のとおりです。「違いは、名前が引用符で囲まれたヘッダー ファイルのみが現在のディレクトリで検索されることです。」
#include "MyFile.hpp"
このバリアントは、独自のプログラムのヘッダー ファイルに使用されます。プリプロセッサは、次の順序でインクルード ファイルを検索します。
- 現在のディレクトリ (つまり、「include」ファイルを含むディレクトリ)
- -I オプションで指定されたディレクトリ (存在する場合)
- システムディレクトリ (例: /usr/include ディレクトリ)
#include <MyFile.hpp>
このバリアントは、システム ヘッダー ファイルに使用されます。プリプロセッサは、次の順序でインクルード ファイルを検索します。
- -I オプションで指定されたディレクトリ (存在する場合)
- システムディレクトリ (例: /usr/include ディレクトリ)
1.e XL C/C++ コンパイラ リファレンス - IBM/AIX
ソース:
両方の文書のタイトルは「XL C/C++ Compiler Reference」です。最初の文書は古い (8.0) ですが、理解しやすいものです。2 つ目は新しい (12.1) ですが、復号化が少し難しくなります。
#include "MyFile.hpp"
このバリアントは、独自のプログラムのヘッダー ファイルに使用されます。プリプロセッサは、次の順序でインクルード ファイルを検索します。
- 現在のディレクトリ (つまり、「include」ファイルを含むディレクトリ)
- -I オプションで指定されたディレクトリ (存在する場合)
- システムディレクトリ (例: /usr/vac[cpp]/include または /usr/include ディレクトリ)
#include <MyFile.hpp>
このバリアントは、システム ヘッダー ファイルに使用されます。プリプロセッサは、次の順序でインクルード ファイルを検索します。
- -I オプションで指定されたディレクトリ (存在する場合)
- システム ディレクトリ (例: /usr/vac[cpp]/include または /usr/include ディレクトリ)
1.e 結論
パターン "" はコンパイラ間で微妙なコンパイル エラーを引き起こす可能性があり、現在 Windows Visual C++、Linux g++、Oracle/Solaris CC、および AIX XL の両方で作業しているため、これは受け入れられません。
とにかく、"" で説明されている機能の利点はとにかく面白くないので...
2. {namespace}/header.hpp パターンを使用する
私は職場で見ました (つまり、これは理論ではありません。これは現実の、つらい専門的経験です)。同じ名前の 2 つのヘッダーがあり、1 つはローカル プロジェクト ディレクトリにあり、もう 1 つはグローバル インクルードにあります。
"" パターンを使用していて、そのファイルがローカル ヘッダーとグローバル ヘッダーの両方に含まれていたため、奇妙なエラーが表示されたときに、実際に何が起こっているのかを理解する方法がありませんでした。
インクルードでディレクトリを使用すると、ユーザーが次のいずれかを記述する必要があったため、時間を節約できました。
#include <MyLocalProject/Header.hpp>
また
#include <GlobalInclude/Header.hpp>
その間、あなたはそれに気付くでしょう
#include "Header.hpp"
正常にコンパイルされるため、問題はまだ隠されていますが、
#include <Header.hpp>
通常の状況ではコンパイルされません。
したがって、<> 表記に固執すると、開発者は適切なディレクトリを含むインクルードのプレフィックスを付けることが必須になり、"" よりも <> を好むもう 1 つの理由になります。
3. 結論
<> 表記と名前空間表記の両方を一緒に使用すると、デフォルトのインクルード ディレクトリのみを検索する代わりに、プリコンパイラからファイルを推測する可能性がなくなります。
もちろん、標準ライブラリは通常どおり含まれています。つまり、次のとおりです。
#include <cstdlib>
#include <vector>