文章目录

  • 前言
  • magic_enum
    • 简单介绍
    • 具体使用
    • 原理简述
    • 局限性
  • 简化与改进
  • 总结

前言

C++11引入了强类型的枚举类 enum class 用来代替旧风格枚举enum,新引入的 enum class 具有诸多优点:防止命名空间污染,不能隐式的转换为整型,防止不同类型的枚举相互赋值,支持前置声明。当然它也不是只有优点,因为类型不能隐式转换成int,所以在使用或者输出时需要使用 static_cast 进行转换,不过即便使用 static_cast 可以转换后输出,也不便于我们辨识枚举的值,如果想输出枚举定义时的名字就需要使用一些魔法了。

magic_enum

因为C++本身不支持反射,或者说反射能力极弱,所以想反射我们必须自己实现一些东西,比如 UE 引擎就为C++写了一套自己的反射标签,而我们想获得枚举定义时的名字就需要自己记录了,因为编译后的枚举一般都转化成了整数,一个简单粗暴的想法是在定义时为每个枚举值同时指定一个同名字符串,构成map存储下来,不过我们不想每次都自己来做这件事,要是有人能帮忙就好了,这不它来了, magic_enum 就可以帮你实现这个愿望。

简单介绍

magic_enum 是一个单头文件的开源库,使用方便,可以轻松帮你实现打印枚举值定义时名字的需求,另外除了可以实现这个功能,还可以根据字符串生成枚举值,根据整数生成枚举值,获取枚举值数组,获取枚举值和名字对应的数字组等等,简直是一个封装了枚举操作的宝库。

具体使用

直接引用头文件 magic_enum.hpp,然后调用函数 magic_enum::enum_name(enum_xxx) 即可:

#include <iostream>
#include "magic_enum.hpp"enum class WeekDay
{WD_SUNDAY = 0,WD_MONDAY,WD_TUESDAY,WD_WEDNESDAY,WD_THURSDAY,WD_FRIDAY,WD_SATURDAY,
};int main()
{WeekDay day = WeekDay::WD_MONDAY;std::cout << "enum value: " << static_cast<std::underlying_type<WeekDay>::type>(day) << "\n";std::cout << "enum name:  " << magic_enum::enum_name(day) << "\n";return 0;
}

编译运行如下:

$ g++ testenum.cpp -std=c++17 && ./a.out
enum value: 1
enum name:  WD_MONDAY

原理简述

很神奇对不对,其实枚举值转换成字符串这一步,是是利用了函数模板和 __PRETTY_FUNCTION__ 组合使用获得到的,也就是对 __PRETTY_FUNCTION__ 进行截取得到的字符串。

__PRETTY_FUNCTION__ 在预编译阶段会替换成带有参数的函数名,比如 constexpr auto magic_enum::detail::n() [with E = WeekDay; E e = WD_MONDAY] 从中截取出 WD_MONDAY 就可以了。

局限性

为了实现从字符串到枚举值的转换,这个库的内部定义了一个整数范围,默认从-128到128,用于遍历查找字符串对应的枚举值是多少,并且在代码中加了 static_assert 来判断范围,如果超过了这个范围就会报编译错误,这个范围可以通过修改源码中的 MAGIC_ENUM_RANGE_MINMAGIC_ENUM_RANGE_MAX 重新编译来修改,在这个范围之外还有个最大值 std::numeric_limits<std::uint16_t>::max 的限制。

这个最大限制也是可以改的,不过我尝试把 MAGIC_ENUM_RANGE_MAX 改到上限值 32767 之后编译时间明显变成,编译过程变得异常的慢,单个文件编译30秒,所以不建议把这个值调太大。

对比一下不使用 magic_enum 和使用它之后生成的汇编代码,从100多行扩充到1000多行,利用 type_traits 生成了大量的函数:

....type   _ZN10magic_enum6detail7names_vI7WeekDayEE, @gnu_unique_object.size   _ZN10magic_enum6detail7names_vI7WeekDayEE, 112
_ZN10magic_enum6detail7names_vI7WeekDayEE:.quad   9.quad   _ZN10magic_enum6detail11enum_name_vI7WeekDayLS2_0EEE.quad   9.quad   _ZN10magic_enum6detail11enum_name_vI7WeekDayLS2_1EEE.quad   10.quad   _ZN10magic_enum6detail11enum_name_vI7WeekDayLS2_2EEE.quad   12.quad   _ZN10magic_enum6detail11enum_name_vI7WeekDayLS2_3EEE.quad   11.quad   _ZN10magic_enum6detail11enum_name_vI7WeekDayLS2_4EEE.quad   9.quad   _ZN10magic_enum6detail11enum_name_vI7WeekDayLS2_5EEE.quad   11.quad   _ZN10magic_enum6detail11enum_name_vI7WeekDayLS2_6EEE.weak   _ZN10magic_enum6detail11enum_name_vI7WeekDayLS2_0EEE
...

简化与改进

其实我最想要的还是通过枚举值转化转化成字符串名称的功能,可以将这个开源库简化一下,仅保留这个功能,这样也不会有范围限制了,感觉这个库为了实现从字符串到枚举值转换背负了太多,去掉它会很清爽。

总结

  • magic_enum 是一个开源的、单头文件的、枚举操作工具箱
  • magic_enum 可以实现枚举值到字符串、字符串到枚举值、获取所有枚举名等多种操作
  • magic_enum 本身对枚举值有范围限制,默认是 [-128, 128], 可通过 MAGIC_ENUM_RANGE_MINMAGIC_ENUM_RANGE_MAX 修改
  • 不建议将 magic_enum 默认枚举范围改的太大,这会明显拖慢编译时间

==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==


世界上有那么多美好,不要跟自己过不去,总是揪着那些角落里的肮脏不放。我们无法选择抓到什么牌,但可以决定怎么把已经抓到手的牌打出去,摆烂是一天,奋斗也是一天,究竟要怎么做,取决于你自己~

推荐一个C++枚举转字符串的开源项目magic_enum相关推荐

  1. 推荐一个非常火爆的电商开源项目!

    今日推荐 推荐一款开源 Java 版的视频管理系统 推荐3个快速开发平台 前后端都有 项目经验又有着落了 14个项目 今天给大家推荐一个商城项目,电商是现在非常火热的方向,网上购物也成为了我们最为日常 ...

  2. 推荐一个动漫风格转换的开源项目!可在线运行

    文 | 超神经 源 | HyperAI AnimeGANv2 最近发布了一项更新,由社区贡献者开发,通过 Gradio 实现了一个可以在线运行的 Demo,发布在 huggingface 上. 访问链 ...

  3. 推荐一个非常好的行为验证码开源项目!

    项目介绍 行为验证码采用嵌入式集成方式,接入方便,安全,高效,抛弃了传统字符型验证码展示-填写字符-比对答案的流程,采用验证码展示-采集用户行为-分析用户行为流程,用户只需要产生指定的行为轨迹,不需要 ...

  4. python开源库推荐_推荐5个值得关注的Python开源项目

    原标题:推荐5个值得关注的Python开源项目 今天小编看到了五个开源项目,觉得还错,推荐给大家. 1.Wagtail CMS Wagtail是一个基于Django的CMS系统 它拥有优质的用户体验 ...

  5. python炫酷特效代码_推荐几个炫酷的 Python 开源项目

    推荐几个炫酷的 Python 开源项目 项目一: Supervisor 简介: Supervisor 是实际企 业常用的一款 Linux/Unix 系统下的一个进程管理工具, 基于 Python 开发 ...

  6. 推荐标星 100 K 的 GitHub 开源项目

    推荐标星 100 K 的 GitHub 开源项目 原文见:推荐 10 个标星 100 K 的 GitHub 开源项目 以下摘录部分: Build Your Own X (GitHub Star:102 ...

  7. 这套ai的思维让我感到了一个细思极恐的开源项目

    这套ai的思维让我感到了一个细思极恐的开源项目 去年,一款角色扮演游戏在国内市场悄然崛起,并在年轻人群体中得到了广泛传播,它有着一个响当当的的名字,叫「剧本杀」. 剧本杀玩法非常简单. 在游戏开始前, ...

  8. 微人事 star 数超 10k 啦!聊聊如何打造一个 star 数超 10k 的开源项目

    看了下,微人事(https://github.com/lenve/vhr)项目 star 数超 10k 啦,松哥第一个 star 数过万的开源项目就这样诞生了. 两年前差不多就是现在这个时候,松哥所在 ...

  9. 微人事 star 数超 10k,如何打造一个 star 数超 10k 的开源项目

    看了下,微人事(https://github.com/lenve/vhr)项目 star 数超 10k 啦,松哥第一个 star 数过万的开源项目就这样诞生了. 两年前差不多就是现在这个时候,松哥所在 ...

最新文章

  1. 本地区间管理 oracle,Oracle:本地表空间管理,字典表空间管理
  2. 产生阻滞的问题 net4.6_识别左束支传导阻滞背后的凶险:Cabrera征和Chapman征|识“图”寻踪...
  3. ADO.NET 2.0 中的新增 DataSet 功能
  4. HTTP状态保持(cookie、session)
  5. 3像素尺寸是多少_纸张的尺寸
  6. thymeleaf 使用页面报错_SpringBoot 使用thymeleaf 跳转页面时,总是提示404找不到页面...
  7. [Java] 蓝桥杯ADV-170 算法提高 数字黑洞
  8. linux 开发板模拟u盘,ARM-Linux开发 - USB Gadget Storage 制作模拟U盘
  9. Cisco公司的CAR流量控制策略
  10. matlab 最小二乘法拟合_最小二乘法辨识1阶离散传递函数
  11. MATLAB最简单教程
  12. 保密协议与竞业限制协议,在劳动法上有什么相关规定吗?
  13. linux幻灯片制作软件,Marp(代码制作幻灯片软件)
  14. SAP 之定义工厂(Plant)
  15. 深信服校园招聘安全攻防A卷
  16. 企业运维之七层负载均衡--Haproxy
  17. Flutter之微信支付实战模板
  18. 优秀的LOGO设计都有哪些共同点,是需要我们借鉴的?
  19. 【面试:并发篇09:多线程:interrupt 方法详解】
  20. windows无法连接到打印机 错误为0x0000011b解决方法

热门文章

  1. 用求阶乘的函数fact(),编程计算1!+2!+3!......+n!的值
  2. ARM嵌入式linux培训班视频 全集
  3. 绘制cadence16.6原理图库
  4. k8s之ingress
  5. 微软Windows Phone卷土归来
  6. android登陆按钮图片素材,Android精美登录界面设计
  7. 国家税务总局全国增值税发票查验平台-1
  8. 拍卖源码架构在拍品详情页上的探索
  9. 单台服务器做redis集群
  10. 关于post数据服务器端接收不全