web-dev-qa-db-ja.com

引数がゼロの可変個引数マクロ

私は呼び出しマクロに取り組んでいます、

#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エラーが発生しますが、それが機能する呼び出しを分離すると

25
Hamza Yerlikaya

更新された質問については、補助マクロを使用してVA_ARGS次のように、引数は期待どおりに展開されます。

#define VA_ARGS(...) , ##__VA_ARGS__
#define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))
21
Ise Wisteria

Gcc/g ++を使用している場合は、次の方法があります。

#define CALL(f,...) FN(f)->call((ref(new LinkedList()), ## __VA_ARGS__))

細かいマニュアル から:

[...]変数引数が省略されているか空の場合、 `## '演算子により、プリプロセッサはその前のコンマを削除します。

したがって、gccには、直面している問題に特化した拡張機能/ハックがあります。

16
mu is too short

GCCを使用している場合は、__VA_ARGS__の前のコンマを飲み込む拡張機能があります。参照: http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html

5
Scott Moonen

___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__)

3
timotheecour

これらの回答に共通するテーマは、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つのコンマが含まれている場合は無害です。 (私はこれが本当かどうかについて考えていませんでした)。
  • @ScootMoonenによると、_##__VA_ARGS___ハックはMSVCの文書化されていない拡張機能です。
1

残念ながら、これはできません。この呼び出しを行うには、別のマクロを定義する必要があります。

VA_ARGSが何にも置き換えられていない場合、無効な引数になってしまうため、フローティング,になってしまいます。

#define CALL0(f) FN(f)->call((ref(new LinkedList())))
0
JProgrammer

f...の一部にし、別のマクロを使用して、fが必要な最初の引数を抽出するだけです。

0
R..