C++ 为什么这是一个结束递归变量宏?

C++ 为什么这是一个结束递归变量宏?,c++,visual-studio,visual-c++,recursion,macros,C++,Visual Studio,Visual C++,Recursion,Macros,以下构造在VisualStudio 2013中编译。我刚刚做了一个新的consoleApplication项目,只更改了main.cpp,所以您可以粘贴它并试用。它显然是创建一个结束递归变量宏 #include "stdafx.h" #include <iostream> using namespace std; #define DEFINE_ENUM_VALUE(name, i) name = i, #define _DEFINE_ENUM_VALUES(i, name, ...

以下构造在VisualStudio 2013中编译。我刚刚做了一个新的consoleApplication项目,只更改了main.cpp,所以您可以粘贴它并试用。它显然是创建一个结束递归变量宏

#include "stdafx.h"
#include <iostream>
using namespace std;

#define DEFINE_ENUM_VALUE(name, i) name = i,
#define _DEFINE_ENUM_VALUES(i, name, ...) DEFINE_ENUM_VALUE(name, i+1)
#define DEFINE_ENUM_VALUES(enum_name, name, ...) enum class enum_name{ \
    DEFINE_ENUM_VALUE(name, 0) _DEFINE_ENUM_VALUES(1, __VA_ARGS__) \
};

DEFINE_ENUM_VALUES(names, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9)

int _tmain(int argc, _TCHAR* argv[])
{
    cout << (int)names::_0 << ' ';
    cout << (int)names::_1 << ' ';
    cout << (int)names::_2 << ' ';
    cout << (int)names::_3 << ' ';
    cout << (int)names::_4 << ' ';
    cout << (int)names::_5 << ' ';
    cout << (int)names::_6 << ' ';
    cout << (int)names::_7 << ' ';
    cout << (int)names::_8 << ' ';
    cout << (int)names::_9 << ' ';
    return 0;
}
这不是打字错误,
名称::_9
的值为2。对于这样定义的每个枚举,最后一个值总是2。我用3-15个参数对其进行了测试

有人知道这里发生了什么吗

为什么MSVC预处理器要多次扩展
DEFINE_ENUM_VALUE
?如果它是预期行为(我对此表示怀疑),为什么它会使最后一个值为2


我还用ideone对它进行了测试,但它并没有按照预期进行编译,注意到
名称之后的所有内容::_1
不是
名称的一部分,即使这是胡说八道,正如chris指出的,这已经被标记,并且也会影响MSVC更新4(在撰写本文时)

我可以确认这是一个用VisualC++的bug。不幸的是,它不符合当前C++ Visual C++版本的分类栏,但是我们将把这个问题保存在数据库中,我们将在VisualC++的未来版本的开发阶段再次查看它。 乔纳森洞穴 Visual C++ Compiler Team < /P> 为了发布相关摘录,当在
\u DEFINE\u ENUM\u VALUES
宏中替换
\u VA\u ARG\uuuuuuuuuuuuuuu参数时,该参数被视为单个标记,而不是多个标记,因此输出

enum class names{ _0 = 0, _1, _2, _3, _4, _5, _6, _7, _8, _9 = 1+1, };
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this is a single token
                                                             for MSVC
而不是

enum class names{ _0 = 0, _1 = 1 +1, };
在执行以下操作时,这可能并不明显

#define printf_macro(format_string, ...) printf(format_string, __VA_ARGS__)

但是在上面的例子中变得很明显。

查看预处理的表单(例如,使用
gcc-C-e
获取,如果您有…)这在gcc中不起作用。MSVC的可变宏不太符合标准,但我无法立即记住更多细节。Boost.PP到处都有有趣的解决方法。@BasileStarynkevitch MSVC有
/P
选项来实现这一点。这提供了一些见解:
enum类名{{u0=0,{u1,{u2,{u3,{u4,{u5,{u6,}u7,{u8,{u9=1+1,}
WeirdI花时间尝试手动向下扩展宏,最终得到
enum类名{{u0=0,{u1=1+1,}。当我注意到你提到同样的预期结果时,我松了一口气。。。我猜宏没有做OP期望它做的事情,这与MSVC错误无关。这个bug使它看起来几乎是正确的,并且掩盖了固有的编码bug。
#define printf_macro(format_string, ...) printf(format_string, __VA_ARGS__)