作为对标准的扩展,##预处理操作符可以用来“吃掉”__VA_ARGS__的后缀逗号。我所有感兴趣的编译器(GCC,clang,MSVC)都支持这一点。
然而,他们的处理方式并不相同。特别是,MSVC以一种我不理解的方式中断(例如下面的例子)。如何编写MYLOG宏,使其在所有平台上都能工作?
示例程序(活链)
#include<cstdio>
#define LOG_HELPER(...) printf(__VA_ARGS__)
#define MYLOG(fmt, ...) LOG_HELPER("mylog: " fmt, ##__VA_ARGS__)
#define MYPRINTF(fmt, ...) printf( "printf: " fmt, ##__VA_ARGS__)
int main() {
// Works in all cases I care about (GCC, clang, MSVC)
MYPRINTF("foo\n");
// Works in GCC+clang, but not MSVC!
MYLOG("foo\n");
return 0;
}MSVC给出的错误是:error C2059: syntax error: ')'
实际上,查看处理后的输出,MYLOG行扩展到:
printf("foo\n", ) // <- Note trailing comma - bad!有没有一种半干净的方法让这件事在任何情况下都有效?
注意:,我在这里的主要愿望是让它以跨平台的方式工作。我意识到##是不标准的,但我更感兴趣的是“MSVC+GCC+clang上的工作”,而不是严格的标准遵从。
另外:我知道__VA_OPT__会加入C++20,但我现在没有选择。
发布于 2020-11-25 22:36:33
简单的方法是根据检测到的编译器有不同的定义。请注意,如果/Zc:preprocessor VA_ARGS是空的,MSVC (至少在开关之前)将吃掉一个后缀逗号。
#define LOG_HELPER(...) printf(__VA_ARGS__)
#if defined(_MSC_VER)
#define MYLOG(fmt, ...) LOG_HELPER("mylog: " fmt, __VA_ARGS__)
#else
#define MYLOG(fmt, ...) LOG_HELPER("mylog: " fmt, ##__VA_ARGS__)
#endif发布于 2020-11-25 22:58:42
我找到了一种适合我的方法:
#define MYLOG(...) LOG_HELPER("mylog: " __VA_ARGS__)遗憾的是,它有点特定于这个特殊用法(组合字符串文字)。
发布于 2022-07-19 22:17:41
聚会有点晚了,但简单地将LOG_HELPER()宏更改为以下内容似乎可以使其在您所关心的所有平台上工作:
#define LOG_HELPER(fmt, ...) printf(fmt, ##__VA_ARGS__)
https://stackoverflow.com/questions/65013414
复制相似问题