繁体   English   中英

零 arguments 的可变参数宏

[英]Variadic macros with zero arguments

我正在处理呼叫宏,

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

当被调用时,

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

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

CALL(HeapSize);

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

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

CALL(print,CALL(HeadSize));

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

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

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

来自精美手册

[...] 如果变量 arguments 被省略或为空,则“##”运算符会导致预处理器删除它前面的逗号。

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

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

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

这些答案的一个共同主题是我们需要一个 GCC 特定的hack。 一种方法是使用标记粘贴##__VAR_ARGS__ ,但粘贴的 arguments 不是宏展开的,这意味着宏不能嵌套。 但是,如果你要做一些 GCC 特定的事情,那么为什么不使用老式的 GCC 扩展:

 #define VARARG_FOO(ZeroOrMoreArgs...) \
     printf("VARARG_FOO: " ZeroOrMoreArgs)

ZeroOrMoreArgs被所有的 arguments(如果有的话)、逗号和所有替换。 这包括递归宏扩展。

  • 然后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__ hack 在标准 C 程序中可能是无害的,因为它们总是至少有一个逗号。 (我没有想过这是否属实)。
  • 根据@ScootMoonen 的说法, ##__VA_ARGS__ hack 是对 MSVC 的无证扩展。

只需使f成为...的一部分,然后使用单独的宏在您需要f的地方提取第一个参数。

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

当您最终得到无效的 arguments 时,当VA_ARGS被任何内容替换时,您最终会得到一个 float ,

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM