31

我正在处理呼叫宏,

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

当被调用时,

CALL(print,2,3,4,5);

将 2 3 4 5 添加到链表(,为此重载)并调用 print 期望链表按预期工作但是有一些不需要参数的调用,

CALL(HeapSize);

它仍然需要一个链接列表,但是一个空列表,上面不起作用,我正在尝试提出一个适用于任何一种风格的宏?

编辑:通过 gcc 文档挖掘我发现在VA_ARGS之前添加 ##会删除 ,当没有参数但我不能嵌套宏时,

CALL(print,CALL(HeadSize));

这会导致 CALL 未定义错误,但是如果我将其工作的调用分开

4

7 回答 7

27

对于更新的问题,通过使用如下辅助宏VA_ARGS,参数将按预期扩展。

#define VA_ARGS(...) , ##__VA_ARGS__
#define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))
于 2011-05-05T11:53:53.003 回答
21

如果你使用 gcc/g++ 有一种方法:

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

来自精美手册

[...] 如果变量参数被省略或为空,'##' 运算符会导致预处理器删除它之前的逗号。

所以 gcc 有一个专门针对您面临的问题的扩展/破解。

于 2011-05-05T00:27:13.323 回答
6

如果您使用的是 GCC,它有一个扩展名来吞噬__VA_ARGS__. 请参阅: http: //gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html

于 2011-05-05T00:27:02.167 回答
6

__VA_OPT__(c++2a) 应该更可靠,例如:来自http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0306r2.html

VA_OPT的规范用例用于可选分隔符:

#define LOG(msg, ...) printf(msg __VA_OPT__(,) __VA_ARGS__)

于 2019-11-26T05:51:12.370 回答
2

这些答案的一个共同主题是我们需要一个 GCC 特定的 hack。一种方法是使用 token-paste ##__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");

优点:

  • 您可以嵌套宏调用,同时拥有零个或多个参数。

缺点:

  • 在标准 C 程序中总是至少有一个逗号的情况下,hack 可能是无害##__VA_ARGS__(我没有想过这是否属实)。
  • 根据@ScootMoonen 的说法,##__VA_ARGS__黑客是对 MSVC 的无证扩展。
于 2014-04-18T16:16:41.637 回答
1

只需制作f,...并使用单独的宏在您需要的地方提取第一个参数f

于 2011-05-05T01:12:14.617 回答
0

不幸的是,这是无法做到的。您需要定义一个单独的宏来执行此调用。

VA_ARGS被任何内容替换时,你最终得到无效参数,你最终得到一个浮动,

#define CALL0(f) FN(f)->call((ref(new LinkedList())))
于 2011-05-05T00:25:33.900 回答