私は呼び出しマクロに取り組んでいます、
#define CALL(f,...) FN(f)->call((ref(new LinkedList()), __VA_ARGS__))
呼び出されたとき、
CALL(print,2,3,4,5);
リンクリストに23 4 5を追加し(そうするためにオーバーロードされます)、引数を必要としない呼び出しがある場合でも、期待どおりに機能するリンクリストを期待するprintを呼び出します。
CALL(HeapSize);
それでもリンクリストが必要ですが、上記の空のリストは機能しません。どちらのスタイルでも機能するマクロを考え出そうとしていますか?
編集:gccドキュメントを掘り下げるVA_ARGSの前に##を追加すると、引数がないのにマクロをネストできない場合に、が削除されることがわかりました。
CALL(print,CALL(HeadSize));
これにより、CALL not definedエラーが発生しますが、それが機能する呼び出しを分離すると
更新された質問については、補助マクロを使用してVA_ARGS
次のように、引数は期待どおりに展開されます。
#define VA_ARGS(...) , ##__VA_ARGS__
#define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))
Gcc/g ++を使用している場合は、次の方法があります。
#define CALL(f,...) FN(f)->call((ref(new LinkedList()), ## __VA_ARGS__))
細かいマニュアル から:
[...]変数引数が省略されているか空の場合、 `## '演算子により、プリプロセッサはその前のコンマを削除します。
したがって、gccには、直面している問題に特化した拡張機能/ハックがあります。
GCCを使用している場合は、__VA_ARGS__
の前のコンマを飲み込む拡張機能があります。参照: http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html 。
___VA_OPT__
_(c ++ 2a)は、より信頼性が高いはずです。例:from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0306r2.html
VA_OPTの標準的なユースケースは、オプションのセパレーターの場合です。
#define LOG(msg, ...) printf(msg __VA_OPT__(,) __VA_ARGS__)
これらの回答に共通するテーマは、GCC固有のハックが必要であるということです。 1つの方法は、トークン貼り付け_##__VAR_ARGS__
_を使用することですが、貼り付けられた引数はマクロ展開されません。つまり、マクロをネストすることはできません。しかし、とにかくGCC固有のことを行う場合は、昔ながらのGCC拡張機能を使用してみませんか。
_ #define VARARG_FOO(ZeroOrMoreArgs...) \
printf("VARARG_FOO: " ZeroOrMoreArgs)
_
ZeroOrMoreArgs
は、すべての引数(存在する場合)、コンマ、およびすべてに単純に置き換えられます。これには、再帰的なマクロ展開が含まれます。
VARARG_FOO()
はprintf("VARARG_FOO: ")
に展開されますVARARG_FOO("I iz %d", 42)
はprintf("VARARGFOO: " "I iz %d", 42)
に展開されます最後に
_ #define NEST_ME "I tawt I taw a puddy tat"
VARARG_FOO("The evil one says %s", NEST_ME);
_
に拡大します
_ printf("VARARG_FOO: " "The evil one says %s", "I tawt I taw a puddy tat");
_
長所:
短所:
##__VA_ARGS__
_ハックmightは、標準のCプログラムでは、常に少なくとも1つのコンマが含まれている場合は無害です。 (私はこれが本当かどうかについて考えていませんでした)。##__VA_ARGS__
_ハックはMSVCの文書化されていない拡張機能です。残念ながら、これはできません。この呼び出しを行うには、別のマクロを定義する必要があります。
VA_ARGSが何にも置き換えられていない場合、無効な引数になってしまうため、フローティング,
になってしまいます。
#define CALL0(f) FN(f)->call((ref(new LinkedList())))
f
を...
の一部にし、別のマクロを使用して、f
が必要な最初の引数を抽出するだけです。