为什么这是一个最终递归可变参数宏?

2024-03-06

以下构造在 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

This is not拼写错误,其值names::_9是 2。对于像这样定义的每个枚举都是这种情况,最后一个值始终是 2。我用 3-15 个参数的整个范围进行了测试。

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

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

我还用 ideone 对其进行了测试,它确实未能按预期编译,注意到之后的所有内容names::_1不属于names.


即使这是无稽之谈,正如克里斯指出的那样,这已被标记“不会修复” https://connect.microsoft.com/VisualStudio/feedback/details/380090/variadic-macro-replacement并且还会影响 MSVC Update4(在撰写本文时)

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

乔纳森·凯夫斯 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__)

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么这是一个最终递归可变参数宏? 的相关文章

随机推荐

  • 转换为具有相同数据成员布局但实现不同的类是否安全?

    第一个类将用于私有继承 以确保布局完全相同 这应该可以保证铸造安全 include
  • Angular 构建无法在服务器上运行

    我正在尝试在服务器上运行我的 AngularJS 前端 我正在使用 Yeoman 来构建应用程序 我上传了非常基本的 hello world 应用程序 并获得了未加载 JavaScript 的纯 HTML 文本 Chrome 中的控制台是这
  • 在 Mac 上使用 XAMPP 安装 XDebug for PHP

    我有一台安装了全新 OSX Mojave 的 Mac 我下载了 XAMPP 7 3 并安装 本地 Apache Web 服务器正常工作 我从仪表板获得的 PHPInfo 显示了 php ini 文件的所有正确信息 即 Application
  • Django:选择性地将 CSS 样式应用到测验单选按钮

    我让用户进行测验 在每个问题之后 我想向他们展示他们的答案是正确还是错误 正确的答案应以绿色突出显示 他们的答案 如果不正确 应以红色突出显示 使用 Twitter Bootstrap 样式 我目前正在 Django 和 HTML 中渲染测
  • D3js - 使用 d3.json 从“JSON 数据”输入绘制折线图

    我最近开始学习 D3 js 并遇到了一些问题 这是我到目前为止所尝试过的 这是我的JS d3 json js sample2 json function data var canvas d3 select body append svg a
  • Typescript 扩展方法编译但在运行时不起作用

    我用一个简单的方法扩展了 Typescript 中的 String 原型 字符串扩展 ts String prototype toCleanedTitleCase function string let titleCase this rep
  • 如何从 xaxis 中删除空因子

    尝试使用 filter select 和无光泽的工作制作交互式绘图条形图 我正在处理许多机场 gt 100 个 的数据 条形图通常过于拥挤 无法支持用户将一个机场 APT x 观察到的性能 值 VAL 与对等机场的子集进行比较 这个想法是使
  • 印度的 R 包?

    我正在美国 R 中以县为基础进行大量统计分析 但我也想对印度做一些研究 我找到了州地图 但在 R 中没有找到区地图 我可以在 d3 js 中找到这样的东西 但我不想放弃 R 印度是否有类似于 地图 的 R 包 您可以使用来自GADM htt
  • 使用 boost::asio::async_read() 的问题

    这是我使用的代码 class Server void Server accepted std cout lt lt Accepted lt lt std endl boost array
  • 创建新的 virtualenv 挂起

    我有一台 MacBook Pro 我从 pylonsbook com virutalenv py 下载了 virtualenv py 当我输入 python virtualenv py no site packages env 它输出 Ne
  • CoreData Swift 和瞬态属性获取器

    关于在 Swift 中使用 Core Data 时实现计算属性有什么建议吗 使用生成的 ManagedObject 类 我尝试重写 getter 但收到错误 计算属性上不允许使用 NSManaged 这意味着您不能覆盖瞬态 计算的 属性的
  • AngularJs 指令 - 如何从指令内获取属性值

    知道如何从指令内部访问属性值吗 angular module portal directives directive languageFlag routeParams function params return function scop
  • 如何使命名管道在 C++ 和 .NET 之间工作?

    我在让命名管道在 c 和 NET 之间工作方面经历了一段非常艰难的时期 我在创建在 2 个 C 应用程序或 2 个 NET 应用程序之间运行的命名管道时没有遇到任何问题 我对这种通信没有问题 我在某些项目中使用这种情况 C 方面 LPTST
  • SendMessage 模拟右键单击使目标应用程序崩溃

    我正在编写一个 C 自动化工具 由于 Microsoft UI 自动化不提供任何模拟右键单击或弹出上下文菜单的方法 因此我正在使用SendMessage改为执行此操作 我宁愿不使用SendInput因为我不想抓住焦点 当我打电话时SendM
  • 如何下载 WatchKit? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道 WatchKit 何时可供 iOS 开发者下载 Xcode 6 是否会包含一个模拟器以允许在
  • 找不到模块“./App.svelte”或其相应的类型声明

    我有一个将电子与 svelte 集成以及打字稿支持集成的设置 当我运行rollup编译 svelte 应用程序的脚本 我找不到模块 App svelte错误如下图所示 Plugin typescript rollup plugin type
  • PHP 警告:非法字符串偏移

    我是 PHP 新手 今天 PHP 从 5 3 3 版本迁移到 5 4 4 版本 Debian Squeeze 到 Debian Wheezy 之后 我从 Apache 日志中收到此错误 gt PHP 警告 xyz 中的非法字符串偏移 php
  • 如何在实体框架 4.3.1 中禁用迁移?

    有没有办法在 Entity Framework 4 3 1 中禁用迁移 我从项目中删除了迁移文件夹以及数据库中生成的表 但它不起作用 如何删除迁移 如果您不想使用迁移 但同时希望 EF 为您创建数据库 则只需设置正确的数据库初始值设定项 D
  • keras.backend的clear_session()方法没有清理拟合数据

    我正在研究不同类型数据质量的拟合精度结果的比较 好数据 是特征值中没有任何NA的数据 坏数据 是特征值中具有 NA 的数据 坏数据 应该通过一些值修正来修复 作为值修正 它可能会用零或平均值替换 NA 在我的代码中 我尝试执行多个拟合过程
  • 为什么这是一个最终递归可变参数宏?

    以下构造在 VisualStudio 2013 中进行编译 我刚刚创建了一个新的 consoleApplication 项目 并且仅更改了主 cpp 因此您只需粘贴它并尝试一下即可 它显然所做的是创建一个最终递归可变参数宏 include