C++预处理器 __VA_ARGS__ 参数数量
简单的问题,我在网上找不到答案。在可变参数宏中,如何查找参数的数量?如果 boost 预处理器有解决方案,我可以接受。
如果有影响,我会尝试将可变数量的宏参数转换为增强预处理器序列、列表或数组,以便进一步重新处理。
Simple question for which I could not find answer on the net. In variadic argument macros, how to find the number of arguments? I am okay with boost preprocessor, if it has the solution.
If it makes a difference, I am trying to convert variable number of macro arguments to boost preprocessor sequence, list, or array for further reprocessing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
我通常使用这个宏来查找一些参数:
完整示例:
它是完全有效的 C99 代码。但它有一个缺点 - 你不能在没有参数的情况下调用宏
SUM()
,但 GCC 有一个解决方案 - 请参阅 此处。因此,对于 GCC,您需要像这样定义宏:
即使参数列表为空,它也能工作
I usually use this macro to find a number of params:
Full example:
It is completely valid C99 code. It has one drawback, though - you cannot invoke the macro
SUM()
without params, but GCC has a solution to it - see here.So in case of GCC you need to define macros like this:
and it will work even with empty parameter list
这实际上取决于编译器,并且不受任何标准支持。
不过,这里有一个宏实现 进行计数:
This is actually compiler dependent, and not supported by any standard.
Here however you have a macro implementation that does the count:
如果您使用 C++11,并且需要该值作为 C++ 编译时常量,一个非常优雅的解决方案是:
请注意:计数完全在编译时发生,并且可以在编译时使用该值整数是必需的,例如作为 std::array 的模板参数。
If you are using C++11, and you need the value as a C++ compile-time constant, a very elegant solution is this:
Please note: the counting happens entirely at compile time, and the value can be used whenever compile-time integer is required, for instance as a template parameter to std::array.
为了方便起见,这里有一个适用于 0 到 70 个参数的实现,并且适用于 Visual Studio、GCC 和 Clang。我相信它可以在 Visual Studio 2010 及更高版本中工作,但仅在 VS2013-2022 中进行了测试。
2023 年 1 月更新:我已经测试并确认,使用
/Zc:preprocessor
编译器选项时,非 Microsoft 变体现在可以在 Visual Studio 2019/2022 中运行,该选项 提供完全一致的 C11 和 C17 预处理器。您可以使用_MSVC_TRADITIONAL
预处理器符号来测试是否正在使用此较新的兼容预处理器(但是,我尚未更新下面的示例来执行此操作)。For convenience, here's an implementation that works for 0 to 70 arguments, and works in Visual Studio, GCC, and Clang. I believe it will work in Visual Studio 2010 and later, but have only tested it in VS2013-2022.
Update January 2023: I have tested and confirmed that the non-Microsoft variant will now work in Visual Studio 2019/2022 when using the
/Zc:preprocessor
compiler option, which provides a fully conformant C11 and C17 preprocessor. You can use the_MSVC_TRADITIONAL
preprocessor symbol to test if this newer compliant preprocessor is being used (I have not updated the example below to do this, however).有一些 C++11 解决方案可用于在编译时查找参数数量,但我很惊讶地发现没有人建议像这样简单的事情:
这不需要包含
;
标头。There are some C++11 solutions for finding the number of arguments at compile-time, but I'm surprised to see that no one has suggested anything so simple as:
This doesn't require inclusion of the
<tuple>
header either.这适用于 gcc/llvm 的 0 个参数。
[链接是愚蠢的]
Visual Studio 似乎忽略了用于使用空参数的 ## 运算符。你也许可以用类似的东西来解决这个问题
this works with 0 arguments with gcc/llvm.
[links are dumb]
Visual Studio seems to be ignoring the ## operator used to consume the empty argument. You can probably get around that with something like
使用 msvc 扩展:
适用于 0 - 32 个参数。这个限制可以很容易地扩展。
编辑:
简化版本(适用于 VS2015 14.0.25431.01 Update 3 和 gcc 7.4.0)最多可复制 100 个参数粘贴:
With msvc extension:
Works for 0 - 32 arguments. This limit can be easily extended.
EDIT:
Simplified version (works in VS2015 14.0.25431.01 Update 3 & gcc 7.4.0) up to 100 arguments to copy & paste:
我假设
__VA_ARGS__
的每个参数都以逗号分隔。如果是这样,我认为这应该是一种非常干净的方法。为我从事 clang 4 和 GCC 5.1 的 godbolt 工作。这将在编译时计算,但不会评估预处理器。因此,如果您尝试执行诸如创建 FOR_EACH 之类的操作,那么这是行不通的。
I'm assuming that each argument to
__VA_ARGS__
will be comma separated. If so I think this should work as a pretty clean way to do this.Worked for me on godbolt for clang 4 and GCC 5.1. This will compute at compile time, but won't evaluate for the preprocessor. So if you are trying to do something like making a FOR_EACH, then this won't work.
这里有一个简单的方法来计算 __VA_ARGS__ 的 0 个或多个参数,我的示例假设最多有 5 个变量,但如果需要,您可以添加更多变量。
herein a simple way to count 0 or more arguments of
__VA_ARGS__
, my example assumes a maximum of 5 variables, but you can add more if you want.我发现这里的答案仍然不完整。
我从这里找到的最接近的便携式实现是:
C++ 预处理器 __VA_ARGS__ 参数数量
但它确实如此不能在 GCC 中使用零参数,至少无需
-std=gnu++11
命令行参数。所以我决定将此解决方案与该解决方案合并:
https://gustedt.wordpress.com/2010/06 /08/detect-empty-macro-arguments/
https://godbolt.org/z/3idaKd
c++11
、msvc 2015
、gcc 4.7.1
、clang 3.0
I've found answers here still are incomplete.
The most closest portable implementation I've found from here is:
C++ preprocessor __VA_ARGS__ number of arguments
But it doen't work with the zero arguments in the GCC without at least
-std=gnu++11
command line parameter.So I decided to merge this solution with that:
https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
https://godbolt.org/z/3idaKd
c++11
,msvc 2015
,gcc 4.7.1
,clang 3.0
Boost 预处理器实际上从 Boost 1.49 开始就有这个,如
BOOST_PP_VARIADIC_SIZE(...)
。它的工作尺寸最大为 64。在底层,它与 Kornel Kisielewicz 的答案基本相同。
Boost Preprocessor actually has this as of Boost 1.49, as
BOOST_PP_VARIADIC_SIZE(...)
. It works up to size 64.Under the hood, it's basically the same as Kornel Kisielewicz's answer.
您可以对标记进行 stringfy 和计数:
You can stringfy and count tokens:
编辑:HolyBlackCat 和 Ted Lyngmo 使这段代码变得更简单
试试这个
Edit: HolyBlackCat and Ted Lyngmo made this code a lot simpler
Try this