簡體   English   中英

c++ 遞歸宏無法在 MSVC 上編譯?

[英]c++ recursive macro wont compile on MSVC?

我從 [https://www.scs.stanford.edu/~dm/blog/va-opt.html] 獲得了這個源代碼。 將 MSVC 與 C++20 一起使用不會編譯,但會在其他編譯器上編譯。 為什么? 我該如何解決?

`/* 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__在應該被接受的時候沒有被接受,或者它不能接受宏的排序方式。 以下是錯誤:

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.

眾所周知,MSVC 中的舊預處理器包含許多問題,請參見 Microsoft 的這篇文章 他們的新預處理器可以通過/Zc:preprocessor標志使用,使預處理器更符合標准,也更接近其他主要編譯器所做的。

在這種特定情況下,我認為問題在於舊的預處理器在FOR_EACH_HELPER FOR_EACH_AGAIN 它不應該,因為它后面沒有括號。 比較上述文章中的相應部分“重新掃描宏的替換列表” 警告"not enough arguments for function-like macro invocation 'FOR_EACH_HELPER'"也暗示了這一點。

使用/Zc:preprocessor ,代碼編譯沒有問題。 godbolt的例子。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM