2010-11-26 18 views
13

プリプロセッサの動作の精神モデルが明らかに不完全で、これが私を狂わせてしまっています。プリプロセッサトークンの展開

2つのトークンを連結したいが、2番目のトークンを最初に展開する必要があります。ここで

#define ANSWER 42 

#define FOO foo_ ## ANSWER 

FOOfoo_ANSWERに展開、私はそれがfoo_42になりたいです。だから私は、これは何とか連結前に引数を拡大することを期待してMERGEマクロを定義:

#define MERGE(x, y) x ## y 

#define BAR MERGE(bar_, ANSWER) 

しかしBARはまだbar_ANSWER代わりのbar_42に展開されます。だから私は、別のマクロHELPERを定義します。

#define HELPER(x, y) MERGE(x, y) 

#define BAZ HELPER(baz_, ANSWER) 

そして今BAZが正常にbaz_42に展開されます。現時点では、これは私にとっては魔法のようです。

誰でもこの動作を私に説明できますか?拡張ルールはどのように正確に機能しますか?

+0

この同じ問題について重複して質問していただければ幸いです。私はなぜこの動作が明確に文書化されていないのだろうかと思います。私は、プリプロセッサが動作するアルゴリズムを意味します。 –

+0

@sandundhammika:明確に仕様6.10.3に記載されていますが、いくつかの未定義の動作コーナーがあります。 –

答えて

7

あなたの質問hereへの答え読む:問題はあなたが マクロ置換を持っていたときに文字列化 演算子#でもトークンでもない場合は、プリプロセッサ だけ再帰的にマクロ を拡大することである

を-pasting 演算子##が適用されます。それで、あなたは 間接のいくつかの余分な層を使用する必要が 、あなたは連結[ref]を実行するときにマクロを展開しません 再帰的に展開引数

+0

これは、なぜBOOST_PP_CATですか? –

+0

上記の引用符は正しくないか、少なくとも完全ではありません。マクロを展開するには、2段階のインダイレクションが必要です(VS2017でテストされ、Gnu cppで同じことが報告されています)。間接指示の第2レベルがなぜ必要なのかについての説明を聞きたい。 "#"または "##"を含まない1つのレベル間接指定を持つと、マクロは展開されません。しかし、第2レベルはそうです。 –

3

トークンを連結して トークンの結合演算子を使用することができます。

これを超えるには、間接レベルを使用して、連結前にマクロを展開するためにプリプロセッサを取得します。

#define STEP1(x, y) STEP2(x, y) // x and y will be expanded before the call to STEP2 
#define STEP2(x, y) x ## y   // x and y will not be expanded, just pasted