C++ 零参数的可变宏
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5891221/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Variadic macros with zero arguments
提问by Hamza Yerlikaya
I am working on a call macro,
我正在处理一个呼叫宏,
#define CALL(f,...) FN(f)->call((ref(new LinkedList()), __VA_ARGS__))
which when called,
当被调用时,
CALL(print,2,3,4,5);
adds 2 3 4 5 to the linked list (, is overloaded to do so) and calls print which expects a linked list which works as expected how ever there are some calls which do not require arguments,
将 2 3 4 5 添加到链表(为了这样做而重载)并调用 print ,它需要一个按预期工作的链表,但是有些调用不需要参数,
CALL(HeapSize);
It still takes a linked list but an empty one, above does not work, I am trying to come up with a macro that woud work with either style?
它仍然需要一个链表,但一个空的,上面不起作用,我试图想出一个可以与任何一种风格一起工作的宏?
EDIT: Digging throug gcc docs I found that adding ## before VA_ARGSremoves the , when there are no arguments but with that I can not nest macros,
编辑:通过 gcc 文档挖掘我发现在VA_ARGS之前添加 ##会删除 ,当没有参数但我无法嵌套宏时,
CALL(print,CALL(HeadSize));
this causes CALL not defined error how ever if I separate the the calls it works
如果我将其工作的调用分开,这会导致 CALL not defined 错误如何
采纳答案by Ise Wisteria
As for the updated question, by the use of auxiliary macro VA_ARGS
like
the following, the arguments will be expanded as expected.
至于更新的问题,通过使用如下辅助宏VA_ARGS
,参数将按预期扩展。
#define VA_ARGS(...) , ##__VA_ARGS__
#define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))
回答by mu is too short
If you're using gcc/g++ there is a way:
如果您使用的是 gcc/g++,则有一种方法:
#define CALL(f,...) FN(f)->call((ref(new LinkedList()), ## __VA_ARGS__))
From the fine manual:
来自精美手册:
[...] if the variable arguments are omitted or empty, the `##' operator causes the preprocessor to remove the comma before it.
[...] 如果变量参数被省略或为空,`##' 运算符会导致预处理器删除它前面的逗号。
So gcc has an extension/hack specifically for the problem you are facing.
所以 gcc 有一个专门针对您面临的问题的扩展/黑客。
回答by Scott Moonen
If you are using GCC, it has an extension to swallow up the comma preceding the __VA_ARGS__
. See: http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html.
如果你使用 GCC,它有一个扩展来吞掉__VA_ARGS__
. 请参阅:http: //gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html。
回答by timotheecour
__VA_OPT__
(c++2a) should be more reliable, eg:
from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0306r2.html
__VA_OPT__
(c++2a) 应该更可靠,例如:来自http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0306r2.html
The canonical use case of VA_OPTis for an optional separator:
#define LOG(msg, ...) printf(msg __VA_OPT__(,) __VA_ARGS__)
VA_OPT的规范用例用于可选分隔符:
#define LOG(msg, ...) printf(msg __VA_OPT__(,) __VA_ARGS__)
回答by Adrian Ratnapala
A common theme in these answers is that we need a GCC specific hack. One way is to use the token-paste ##__VAR_ARGS__
, but pasted arguments are not macro expanded, which means that macros cannot be nested. But if you are going to do something GCC specific anyway, then why not use the old-fashioned GCC extension:
这些答案中的一个共同主题是我们需要一个 GCC 特定的 hack。一种方法是使用 token-paste ##__VAR_ARGS__
,但粘贴的参数不是宏扩展的,这意味着宏不能嵌套。但是如果你无论如何都要做一些 GCC 特定的事情,那么为什么不使用老式的 GCC 扩展:
#define VARARG_FOO(ZeroOrMoreArgs...) \
printf("VARARG_FOO: " ZeroOrMoreArgs)
ZeroOrMoreArgs
is simply replaced by all the arguments (if any), commas and all. This includes recursive macro expansion.
ZeroOrMoreArgs
简单地替换为所有参数(如果有)、逗号和所有参数。这包括递归宏扩展。
- then
VARARG_FOO()
expands toprintf("VARARG_FOO: ")
- and
VARARG_FOO("I iz %d", 42)
expands toprintf("VARARGFOO: " "I iz %d", 42)
- 然后
VARARG_FOO()
扩展到printf("VARARG_FOO: ")
- 并
VARARG_FOO("I iz %d", 42)
扩展到printf("VARARGFOO: " "I iz %d", 42)
Finally
最后
#define NEST_ME "I tawt I taw a puddy tat"
VARARG_FOO("The evil one says %s", NEST_ME);
will expand to
将扩展到
printf("VARARG_FOO: " "The evil one says %s", "I tawt I taw a puddy tat");
Pros:
优点:
- You can nest macro invocations, while having zero-or more aguments.
- 您可以嵌套宏调用,同时拥有零个或多个参数。
Cons:
缺点:
- The
##__VA_ARGS__
hack mightbe harmless in standard C programs in the case where they always have at least one comma. (I haven't thought about whether this is true or not). - According to @ScootMoonen the
##__VA_ARGS__
hack is an undocumented extension to MSVC.
- 该
##__VA_ARGS__
黑客可能是在他们总是至少有一个逗号的情况下,标准的C程序无害。(我还没想过这是不是真的)。 - 根据@ScootMoonen 的说法,该
##__VA_ARGS__
hack 是 MSVC 的未公开扩展。
回答by R.. GitHub STOP HELPING ICE
Simply make f
part of the ...
, and use a separate macro to extract the first argument where you need f
.
只需制作 的f
一部分...
,然后使用单独的宏在您需要的地方提取第一个参数f
。
回答by JProgrammer
Unfortunately this cannot be done. You will need to define a separate macro to do this call.
不幸的是,这是无法做到的。您将需要定义一个单独的宏来执行此调用。
As you end up with invalid arguments when VA_ARGSis substituted with nothing you end up with a floating ,
当VA_ARGS被任何内容替换时,您最终会得到无效参数,因此您最终会得到一个浮动,
#define CALL0(f) FN(f)->call((ref(new LinkedList())))