首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++递归宏不会在MSVC上编译?

c++递归宏不会在MSVC上编译?
EN

Stack Overflow用户
提问于 2022-12-03 16:30:07
回答 1查看 61关注 0票数 3

我从https://www.scs.stanford.edu/~dm/blog/va-opt.html.获得了这个源代码使用MSVC和C++20,它不编译,但它确实在其他编译器上编译。为什么?我怎么才能解决这个问题?

代码语言:javascript
复制
`/* compile with:
   c++ -std=c++20 -Wall -Werror make_enum.cc -o make_enum
 */

#include <iostream>

#define PARENS ()

// Rescan macro tokens 256 times
#define EXPAND(arg) EXPAND1(EXPAND1(EXPAND1(EXPAND1(arg))))
#define EXPAND1(arg) EXPAND2(EXPAND2(EXPAND2(EXPAND2(arg))))
#define EXPAND2(arg) EXPAND3(EXPAND3(EXPAND3(EXPAND3(arg))))
#define EXPAND3(arg) EXPAND4(EXPAND4(EXPAND4(EXPAND4(arg))))
#define EXPAND4(arg) arg

#define FOR_EACH(macro, ...)                                    \
  __VA_OPT__(EXPAND(FOR_EACH_HELPER(macro, __VA_ARGS__)))
#define FOR_EACH_HELPER(macro, a1, ...)                         \
  macro(a1)                                                     \
  __VA_OPT__(FOR_EACH_AGAIN PARENS (macro, __VA_ARGS__))
#define FOR_EACH_AGAIN() FOR_EACH_HELPER

#define ENUM_CASE(name) case name: return #name;

#define MAKE_ENUM(type, ...)                    \
enum type {                                     \
  __VA_ARGS__                                   \
};                                              \
constexpr const char *                          \
to_cstring(type _e)                             \
{                                               \
  using enum type;                              \
  switch (_e) {                                 \
  FOR_EACH(ENUM_CASE, __VA_ARGS__)              \
  default:                                      \
    return "unknown";                           \
  }                                             \
}

MAKE_ENUM(MyType, ZERO, ONE, TWO, THREE);

void
test(MyType e)
{
  std::cout << to_cstring(e) << " = " << e << std::endl;
}

int
main()
{
  test(ZERO);
  test(ONE);
  test(TWO);
  test(THREE);
}

/*
  Local Variables:
  c-macro-pre-processor: "c++ -x c++ -std=c++20 -E -"
  End:
*/`

我不知道我的生活出了什么问题。我已经尝试过修改代码,在我看来,__VA_ARGS__应该是不被接受的,或者它不能接受命令宏的方式。以下是错误:

代码语言:javascript
复制
1>make_enum.cc
1>C:\Users\Thomas\source\repos\outoftouch\outoftouch\make_enum.cc(40,1): warning C4003: not enough arguments for function-like macro invocation 'FOR_EACH_HELPER'
1>C:\Users\Thomas\source\repos\outoftouch\outoftouch\make_enum.cc(40,1): warning C4003: not enough arguments for function-like macro invocation 'ENUM_CASE'
1>C:\Users\Thomas\source\repos\outoftouch\outoftouch\make_enum.cc(40,1): error C2059: syntax error: 'case'
1>C:\Users\Thomas\source\repos\outoftouch\outoftouch\make_enum.cc(40,1): error C2065: 'ENUM_CASE': undeclared identifier
1>C:\Users\Thomas\source\repos\outoftouch\outoftouch\make_enum.cc(40,1): error C3861: 'FOR_EACH_HELPER': identifier not found
1>C:\Users\Thomas\source\repos\outoftouch\outoftouch\make_enum.cc(40,1): error C2059: syntax error: ')'
1>C:\Users\Thomas\source\repos\outoftouch\outoftouch\make_enum.cc(40,1): error C2146: syntax error: missing ';' before identifier 'default'
1>C:\Users\Thomas\source\repos\outoftouch\outoftouch\make_enum.cc(40,1): warning C4065: switch statement contains 'default' but no 'case' labels
1>Done building project "outoftouch.vcxproj" -- FAILED.
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-12-03 16:55:45

众所周知,MSVC中的旧预处理器包含许多问题,例如微软的这篇文章。它们的新预处理器可以通过/Zc:preprocessor标志使用,从而使预处理器更加符合标准,并且更接近其他主要编译器所做的工作。

在这种特殊情况下,我认为问题在于旧的预处理器在FOR_EACH_HELPER中错误地扩展了FOR_EACH_HELPER;它不应该,因为它后面没有括号。比较相应的上述文章中的“宏替换列表”一节。警告"not enough arguments for function-like macro invocation 'FOR_EACH_HELPER'"也暗示了这一点。

使用/Zc:preprocessor,代码编译时没有问题。哥德波特上的示例。

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

https://stackoverflow.com/questions/74668523

复制
相关文章

相似问题

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