为什么这是一个end-recursive可变宏? [英] Why is this an end-recursive variadic macro?

查看:171
本文介绍了为什么这是一个end-recursive可变宏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following construct compiles in VisualStudio 2013. I just made a new consoleApplication project and only changed the main .cpp, so you can just paste this and try it out. What it apparently does is create an end-recursive variadic macro.

#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;
}

这不仅编译,而且几乎可以想象。输出为:

This not only compiles, but also works only nearly as one may imagine. The output is this:

0 1 2 3 4 5 6 7 8 2

这是不是错字,值 names :: _ 9 是2.这是这样定义的每个枚举的情况,最后一个值总是2.我测试这个与3-15参数的整个范围。

This is not a typo, the value of names::_9 is 2. And this is the case for every enum defined like this, the last value is always 2. I tested this with a whole range from 3-15 arguments.

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

Does anyone have an idea what's going on here?

为什么MSVC预处理器多次扩展 DEFINE_ENUM_VALUE ?为什么,如果它是想要的行为(我怀疑),它是否使最后的值2?

Why is the MSVC pre-processor expanding DEFINE_ENUM_VALUE multiple times? And why, if it's intended behaviour (which I doubt), does it make the last value 2?

我也测试了它与ideone,预期,注意 names :: _ 1 之后的所有内容不是 names 的一部分。

I also tested it with ideone, and it did fail to compile as expected, noting that everything after names::_1 wasn't part of names.

推荐答案

即使这是无谓的,因为克里斯注意到这已被标记为不会修复,并且还影响MSVC Update4(在编写此文档时)

Even if this is nonsense, as chris noted this has been marked "won't fix" and also affects MSVC Update4 (at the time of writing this)


Hi:我可以确认这是Visual C ++的错误。不幸的是,它不符合当前版本的Visual C ++的分类栏 - 但我们将保留在我们的数据库中的问题,我们将在Visual C ++的未来版本的开发阶段再次查看。

Hi: I can confirm that this is a bug with Visual C++. Unfortunately it does not meet the triage bar for the current release of Visual C++ - but we will keep the issue in our database and we will look at it again during the development phase of a future release of Visual C++.

Jonathan Caves
Visual C ++编译器团队

Jonathan Caves Visual C++ Compiler Team

发布相关摘录,在 _DEFINE_ENUM_VALUES 宏中替换时,code> __ VA_ARG __ 参数被视为单个标记而不是多个,因此输出

to post the relevant excerpts, the __VA_ARG__ parameter when replaced in the _DEFINE_ENUM_VALUES macro, is considered as a single token instead of multiple ones thus outputting

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, };

这样做可能不太明显,例如

this might not be obvious when doing something like

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

但在上述示例中变得明显。

but becomes evident in the example above.

这篇关于为什么这是一个end-recursive可变宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆