以下构造在VisualStudio 2013中编译。我刚刚创建了一个新的consoleApplication项目并且只更改了主.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;
}
这不仅可以编译,而且几乎可以像人们想象的那样工作。输出是这样的:
0 1 2 3 4 5 6 7 8 2
这是不是一个错字,names::_9
的值是2.这就是这样定义的每个枚举的情况,最后一个值总是2.我测试了这个整个范围从3-15个论点。
有谁知道这里发生了什么?
为什么MSVC预处理器多次展开DEFINE_ENUM_VALUE
?为什么,如果它是预期的行为(我怀疑),它是否使最后一个值2?
我还使用ideone对其进行了测试,并且无法按预期编译,并指出names::_1
之后的所有内容都不属于names
。
答案 0 :(得分:1)
即使这是胡说八道,正如克里斯所说,这已标记为"won't fix"并且也会影响MSVC Update4(在撰写本文时)
嗨:我可以确认这是Visual C ++的一个错误。不幸的是,它不符合当前版本的Visual C ++的分类栏 - 但我们将把这个问题保留在我们的数据库中,我们将在未来的Visual C ++版本的开发阶段再次查看它。
Jonathan Caves Visual C ++编译器团队
发布相关的摘录,在__VA_ARG__
宏中替换时_DEFINE_ENUM_VALUES
参数被视为单个令牌而不是多个令牌,因此输出
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__)
但在上面的例子中变得明显。