2016-04-07 16 views
1

私は再帰的マクロを扱っています。しかし、再帰的には展開されていないようです。ここで私が何を意味するか示すために、最小限の作業例です:再帰Cマクロは展開されていません

// ignore input, do nothing 
#define ignore(...) 
// choose between 6 names, depending on arity 
#define choose(_1,_2,_3,_4,_5,_6,NAME,...) NAME 
// if more than one parameter is given to this macro, then execute f, otherwise ignore 
#define ifMore(f,...) choose(__VA_ARGS__,f,f,f,f,f,ignore)(__VA_ARGS__) 
// call recursively if there are more parameters 
#define recursive(first,args...) first:ifMore(recursive,args) 

recursive(a,b,c,d) 
// should print: a:b:c:d 
// prints: a:recursive(b,c,d) 

recursiveマクロが再帰的に自分自身を拡張し、常にコロンで区切られた結果を、連結すべきです。ただし、動作しません。再帰マクロは正しく生成されます(結果はa:recursive(b,c,d)ですが、マクロへの正常な呼び出しが含まれます)。しかし、生成された再帰呼び出しは除外されません。

なぜこれが当てはまるのですが、なぜ私が望む動作を得ることができますか?

+1

「私は、再帰的なマクロに取り組んでいます」 - まあ、それは知ることは困難です何を言いたいのですか:(非再帰マクロはPITAです –

答えて

4

必要な動作を取得できません。 Cプリプロセッサは、設計上、完全にチューリングされていません。

複数のマクロを使用して複数の置換を取得することはできますが、任意の置換回数で真の再帰を達成することはできません。

+0

マクロがここで再び拡大するのを防ぐルールは何ですか?ルールは何ですか? – gexicide

+0

ここでルールを見つけることができます:http://stackoverflow.com/a/12447739/464136 –

1

コンパイラのプリプロセッサは、定義したマクロを展開しません。つまり、マクロ文で見つかった文字列を、定義内で見つかった文字列で置き換えます。例えば、Can we have recursive macros?又はMacro recursive expansion to a sequenceC preprocessor, recursive macros

は、recursive(a,b,c,d)a:recursive(b,c,d)に拡大され、プリプロセッサは、次に、ベースコードの次の行に進みます。文字列を引き続き拡大しようとするためにループしません(私が引用したリンクを参照)。

+1

"マクロ文で見つかった文字列を、定義内で見つかった文字列で盲目的に置き換えます"これはまさに私が望むものですが、ここではありません!は結果として 'recursive(b、c、d)'という文字列になっていますが、 'recursive'の定義では文字列に置き換えられません。 – gexicide

+0

あなたの定義に 'recursive(b、c、d) 'という文字列が含まれているということは重要ではありません。その結果、コンパイルするコードにその文字列を盲目的にコピーします。私が示すリンクに従ってください。 – sabbahillel

+1

@sabbahillel:しかし、ボディに別のマクロが含まれていれば、マクロはそれを拡張します。だから「盲目的にコピーする」とは何の関係もありません。実際、プリプロセッサは目が開いたままである。拡張するマクロを探していますが、既に展開されているマクロは注意深く無視します。 – rici

1

他にも言及したように、Cマクロでは純粋な再帰は不可能です。ただし、再帰的な効果をシミュレートすることは可能です。

ブーストプリプロセッサツールは、CおよびC++の両方のためにも、この操作を行うと、スタンドアローンのライブラリです:

http://www.boost.org/doc/libs/1_60_0/libs/preprocessor/doc/index.html

関連する問題