为什么这是一个结束递归变量宏
Why is this an end-recursive variadic macro?
以下构造在VisualStudio2013中编译。我刚做了一个新的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;
}
这不仅可以编译,而且几乎可以像人们想象的那样工作。输出是这样的:
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
的一部分。
即使这是无稽之谈,正如chris所指出的,这已经被标记为"不会修复";并且还影响MSVC Update4(在撰写本文时)
嗨:我可以确认这是Visual C++的一个错误。不幸的是,它不符合Visual C++当前版本的分类标准,但我们将把这个问题保留在数据库中,并将在未来Visual C++版本的开发阶段再次研究它。
乔纳森·卡维斯Visual C++编译器团队
为了发布相关摘录,在_DEFINE_ENUM_VALUES
宏中替换__VA_ARG__
参数时,会将其视为单个令牌,而不是多个令牌,从而输出
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__)
但是在上面的例子中变得明显。
相关文章:
- 删除映射和分割错误中的一个过去结束元素
- 取消引用结束指针到数组类型的一个
- 结束另一个线程中使用的对象的生存期
- 在C++中,如何在第一个"system()"结束后执行第二个"system()"?
- 我们可以在第一个else-if条件结束后使用另一个else-if条件吗
- 编写一个函数,在开始和结束处添加括号,使所有括号匹配并返回
- 带有文件结束函数的 while 循环重复输出文件中的最后一个数字两次
- 在未满足条件时的任何时刻结束一个段循环
- C :使用文件末端(CTRL Z)结束一个循环似乎打破了我程序的其余部分
- 如何为一个类提供多个开始/结束代理
- C++函数无法到另一个函数并自动结束
- 如何从另一个函数中调用的函数结束程序 (C++)
- 通过在上一个数组结束后立即存储下一个元素来扩展数组
- 无限输入C 计算器要结束计算,需要再进行一个INT
- C 如何结束一个段循环,该循环添加数字而不使用数字作为触发器来结束循环
- 当其中一个结束较早的C 时,杀死所有线程
- 从一个起点遍历一个图形,并在起点C++处结束
- 虽然循环总是提前结束一个循环
- 如何不间断地提前结束一个循环
- 如何在c++中结束一个进程