VisualStudio的参数为零的参数计数宏
Argument counting macro with zero arguments for VisualStudio
本文关键字:参数 VisualStudio 更新时间:2023-10-16
gcc确实支持## __VA_ARGS__
约定中参数为零的参数计数宏。以下是用gcc编译的作品:
#include <stdio.h>
#define NARGS(...) __NARGS(0, ## __VA_ARGS__, 5,4,3,2,1,0)
#define __NARGS(_0,_1,_2,_3,_4,_5,N,...) N
int main()
{
printf("%dn", NARGS()); // prints 0
printf("%dn", NARGS(1)); // prints 1
printf("%dn", NARGS(1, 2)); // prints 2
return 0;
}
有没有一个VisualC++的等价物可以使用零参数宏?接受非标准的扩展或技巧。
EDIT:修复了使用GCC扩展和C++编译器的示例。
以下示例在启用了非标准扩展的VisualStudio 2010及更新版本、gcc和clang中运行良好。在Microsoft编译器中,它假设当参数计数为零时,预处理器将删除AUGMENTER宏中的尾部逗号。这是非标准的,其他地方也有报道。在gcc和clang中,它使用了众所周知的## __VA_ARGS__
非标准扩展。
#include <stdio.h>
#ifdef _MSC_VER // Microsoft compilers
#define EXPAND(x) x
#define __NARGS(_1, _2, _3, _4, _5, VAL, ...) VAL
#define NARGS_1(...) EXPAND(__NARGS(__VA_ARGS__, 4, 3, 2, 1, 0))
#define AUGMENTER(...) unused, __VA_ARGS__
#define NARGS(...) NARGS_1(AUGMENTER(__VA_ARGS__))
#else // Others
#define NARGS(...) __NARGS(0, ## __VA_ARGS__, 5,4,3,2,1,0)
#define __NARGS(_0,_1,_2,_3,_4,_5,N,...) N
#endif
int main()
{
// NARGS
printf("%dn", NARGS()); // Prints 0
printf("%dn", NARGS(1)); // Prints 1
printf("%dn", NARGS(1, 2)); // Prints 2
fflush(stdout);
#ifdef _MSC_VER
// NARGS minus 1
printf("n");
printf("%dn", NARGS_1(1)); // Prints 0
printf("%dn", NARGS_1(1, 2)); // Prints 1
printf("%dn", NARGS_1(1, 2, 3)); // Prints 2
#endif
return 0;
}
宏使用真实编译器、Wandbox和Webcompiler 进行了测试
以下是一些可与gcc(5.3)一起使用的代码ANDVisualStudio2010:
#include <stdio.h>
#define expand(x) x
#define prefix(...) 0,##__VA_ARGS__
#define lastof10(a,b,c,d,e,f,g,h,i,j,...) j
#define sub_nbarg(...) expand(lastof10(__VA_ARGS__,8,7,6,5,4,3,2,1,0))
#define nbarg(...) sub_nbarg(prefix(__VA_ARGS__))
#define test(...) printf("(%s) ---> %dn",""#__VA_ARGS__,nbarg(__VA_ARGS__))
int main ()
{
test() ; // () ---> 0
test(1) ; // (1) ---> 1
test(1,2) ; // (1,2) ---> 2
test(1,2,3) ; // (1,2,3) ---> 3
test(1,2,3,4) ; // (1,2,3,4) ---> 4
test(1,2,3,4,5) ; // (1,2,3,4,5) ---> 5
test(1,2,3,4,5,6) ; // (1,2,3,4,5,6) ---> 6
return 0 ;
}
你能试试吗:
#define __NARGS(_1, _2, _3, _4, _5, VAL, ...) VAL
#define NARGS(...) (sizeof(#__VA_ARGS__) == sizeof("") ? 0 : __NARGS(__VA_ARGS__, 5, 4, 3, 2, 1))
这适用于g++(Demo)。
使用@Jarod42的思想和BOOST的BOOST _PP_VARIADIC_SIZE可以写如下。
#include <stdio.h>
#include <boost/preprocessor/variadic/size.hpp>
#define FOO(...) (sizeof(""#__VA_ARGS__) == sizeof("") ? 0 : BOOST_PP_VARIADIC_SIZE(__VA_ARGS__))
int main()
{
printf("%dn", FOO()); // prints 0
printf("%dn", FOO(1)); // prints 1
printf("%dn", FOO(1, 2)); // prints 2
return 0;
}
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 使用指向成员的指针将成员函数作为参数传递
- 在 VisualStudio 2013 中,扣除失败,第一个模板参数是特定类型(反过来是任意模板化的)
- VisualStudio的参数为零的参数计数宏