变量宏,零参数

Ham*_*aya 20 c++ gcc c-preprocessor variadic-macros

我正在研究一个调用宏,

#define CALL(f,...) FN(f)->call((ref(new LinkedList()), __VA_ARGS__))
Run Code Online (Sandbox Code Playgroud)

在被叫时,

CALL(print,2,3,4,5);
Run Code Online (Sandbox Code Playgroud)

将2 3 4 5添加到链接列表(,重载以执行此操作)并调用print,其中需要链接列表按预期工作,但有些调用不需要参数,

CALL(HeapSize);
Run Code Online (Sandbox Code Playgroud)

它仍然需要一个链接列表,但是一个空的,上面不起作用,我试图想出一个宏,它可以使用任何一种风格吗?

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

CALL(print,CALL(HeadSize));
Run Code Online (Sandbox Code Playgroud)

如果我分离它的工作调用,这会导致CALL未定义错误

Ise*_*ria 20

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

#define VA_ARGS(...) , ##__VA_ARGS__
#define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))
Run Code Online (Sandbox Code Playgroud)

  • 我一直在使用这个技巧,直到我发现在编译C99甚至C11时在gcc的迂腐模式下,这会产生警告.好吧,不完全是这个宏定义本身,而是调用具有零可变零件的可变参数宏.为什么,哦,为什么他们不允许它在C11标准?! (6认同)
  • `__VA_OPT__` 将是你的朋友@AlexanderAmelkin (2认同)

mu *_*ort 16

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

#define CALL(f,...) FN(f)->call((ref(new LinkedList()), ## __VA_ARGS__))
Run Code Online (Sandbox Code Playgroud)

精细手册:

[...]如果省略变量参数或为空,则`##'运算符会使预处理器删除前面的逗号.

因此,gcc专门针对您所面临的问题进行扩展/破解.

  • 不仅 gcc/g++,也适用于 IAR 的编译器! (2认同)

小智 5

如果您使用的是GCC,则它具有扩展名,可以吞下之前的逗号__VA_ARGS__。参见:http : //gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html

  • @vanza:实际上,MSVC会“自动”为您完成操作-如果宏中有序列`,__VA_ARGS__`,而`__VA_ARGS__`为空,它将自动吞下(删除)`,`。如果它不能在两个令牌之间合并,它也会忽略“ ##”,因此gcc扩展名是偶然的。 (5认同)

tim*_*our 5

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