C規格では、次の3つの形式が指定されています#include
。
#include <file>
#include "file"
#include ANYTHING ELSE
前の2つのケースでは、マクロ展開が行われないため、動作を変更する方法はありません。3番目のケースでは、C99は次のように述べています(§6.10.2p4):
ディレクティブの後の前処理トークン#include
は[マクロ拡張]です。すべての置換の後に生じるディレクティブは、前の2つの形式のいずれかに一致する必要があります[脚注:隣接する文字列リテラルは単一の文字列リテラルに連結されないことに注意してください]。<と>の前処理トークンのペアまたは"文字のペアの間の一連の前処理トークンを組み合わせて単一のヘッダー名の前処理トークンにする方法は、実装によって定義されます。
わずかに異なりますが、事実上同等の表現がC++98§16.2p4に表示されます。
「shall」を含む文には厳しい要件があります。この場合、プログラムは、で始まり、で終わるトークンのシーケンス、またはで始まり、で終わるANYTHING ELSE
トークンのシーケンス以外に展開されると、形式が正しくありません。トークンのそのシーケンスの正確な解釈は実装で定義されていますが、脚注は文字列リテラルの連結を明確に禁止していることに注意してください。<
>
"
したがって、の展開__FILE__
は文字列定数であるため、でそれを使用する唯一の方法は次の#include
とおりです。
#include __FILE__
あなたが発見したように、これは無限の再帰につながり、そして
#define LT <
#define GT >
#include LT __FILE__ etc GT
これは、私が便利にテストできるすべてのコンパイラに面白いが役に立たない効果をもたらします。上記が次の名前のファイルにあると仮定しますtest.c
:
"test.c" etc
GCCは、引用符とスペースを逐語的に含めて、という名前のファイルを開こうとします。
- clangはさらにリテラルであり、同じファイル名を検索しますが、先頭と末尾にスペースがあります。
- MSVCマクロ- (これは適合違反であると私は考えています)のみを展開し、一致するものがないと文句を言ってから、という名前のファイルを開こうとします。
LT
>
__FILE__ etc GT
(GCCの振る舞いはここに文書化されています;あなたは他のことについてあなた自身でいます。)
tl; dr:プリプロセッサの内部からやりたいことをする方法はありません。ビルドシステムから含めるファイルの名前を調べて、-D
スイッチでコンパイラに通知することをお勧めします(Unixyシステムでは、二重引用符が必要です。CMD-DINCLUDEME='"includeme.h"'
は話せません)。