首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >##__VA_ARGS__与其他编译器的MSVC处理

问##__VA_ARGS__与其他编译器的MSVC处理
EN

Stack Overflow用户
提问于 2020-11-25 22:13:27
回答 4查看 887关注 0票数 2

作为对标准的扩展,##预处理操作符可以用来“吃掉”__VA_ARGS__的后缀逗号。我所有感兴趣的编译器(GCC,clang,MSVC)都支持这一点。

然而,他们的处理方式并不相同。特别是,MSVC以一种我不理解的方式中断(例如下面的例子)。如何编写MYLOG宏,使其在所有平台上都能工作?

示例程序(活链)

代码语言:javascript
复制
#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行扩展到:

代码语言:javascript
复制
printf("foo\n", )  // <- Note trailing comma - bad!

有没有一种半干净的方法让这件事在任何情况下都有效?

注意:,我在这里的主要愿望是让它以跨平台的方式工作。我意识到##是不标准的,但我更感兴趣的是“MSVC+GCC+clang上的工作”,而不是严格的标准遵从。

另外:我知道__VA_OPT__会加入C++20,但我现在没有选择。

EN

回答 4

Stack Overflow用户

发布于 2020-11-25 22:36:33

简单的方法是根据检测到的编译器有不同的定义。请注意,如果/Zc:preprocessor VA_ARGS是空的,MSVC (至少在开关之前)将吃掉一个后缀逗号。

代码语言:javascript
复制
#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
票数 1
EN

Stack Overflow用户

发布于 2020-11-25 22:58:42

我找到了一种适合我的方法:

代码语言:javascript
复制
#define MYLOG(...)    LOG_HELPER("mylog: " __VA_ARGS__)

遗憾的是,它有点特定于这个特殊用法(组合字符串文字)。

票数 1
EN

Stack Overflow用户

发布于 2022-07-19 22:17:41

聚会有点晚了,但简单地将LOG_HELPER()宏更改为以下内容似乎可以使其在您所关心的所有平台上工作:

#define LOG_HELPER(fmt, ...) printf(fmt, ##__VA_ARGS__)

工作实例

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65013414

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档