[英]c++ recursive macro wont compile on MSVC?
I got this source code from [https://www.scs.stanford.edu/~dm/blog/va-opt.html].我从 [https://www.scs.stanford.edu/~dm/blog/va-opt.html] 获得了这个源代码。 Using MSVC with C++20 it doesn't compile, but it does compile on other compilers.
将 MSVC 与 C++20 一起使用不会编译,但会在其他编译器上编译。 Why?
为什么? And how can I fix that?
我该如何解决?
`/* 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:
*/`
I cant figure out for the life of me what the problem is.我无法弄清楚我的生活是什么问题。 I've tried modifying the code, to me it seems that
__VA_ARGS__
isn't accepted when it should be, or that it can't accept the way the macros are ordered.我试过修改代码,对我来说似乎
__VA_ARGS__
在应该被接受的时候没有被接受,或者它不能接受宏的排序方式。 Here are the errors:以下是错误:
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.
The old preprocessor in MSVC is known to contain many problems, see eg this article by Microsoft.众所周知,MSVC 中的旧预处理器包含许多问题,请参见 Microsoft 的这篇文章。 Their new preprocessor can be used via the
/Zc:preprocessor
flag, causing the preprocessor to be more standard conform and also closer to what other major compilers do.他们的新预处理器可以通过
/Zc:preprocessor
标志使用,使预处理器更符合标准,也更接近其他主要编译器所做的。
In this specific case, I think the problem is that the old preprocessor incorrectly expands FOR_EACH_AGAIN
in FOR_EACH_HELPER
early;在这种特定情况下,我认为问题在于旧的预处理器在
FOR_EACH_HELPER
FOR_EACH_AGAIN
it shouldn't, because it is not followed by parentheses.它不应该,因为它后面没有括号。 Compare the corresponding section "Rescanning replacement list for macros" in the above mentioned article .
比较上述文章中的相应部分“重新扫描宏的替换列表” 。 The warning
"not enough arguments for function-like macro invocation 'FOR_EACH_HELPER'"
also hints at that.警告
"not enough arguments for function-like macro invocation 'FOR_EACH_HELPER'"
也暗示了这一点。
With /Zc:preprocessor
, the code compiles without issues.使用
/Zc:preprocessor
,代码编译没有问题。 Example on godbolt . godbolt的例子。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.