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

2023-05-16

文章目录

  • 前言
  • 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 默认枚举范围改的太大,这会明显拖慢编译时间

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

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

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

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

  • c++ enum class转int

    示例 enum class 定义 span class token keyword enum span span class token keyword class span span class token class name Colo
  • C++中的枚举(enum)

    C 43 43 中的枚举 enum 枚举类型 enumeration 是 C 43 43 中的一种派生数据类型 xff0c 它是由用户定义的若干枚举常量的集合 枚举是一个数值集合 xff0c 是给一个值命名的一种方法 如果想要使用整数来表示
  • C++枚举enum使用详解

    目录 一 什么是枚举enum WHAT 二 使用枚举enum的场景 WHEN and WHERE 三 如何使用枚举enum HOW 1 xff09 枚举的定义 2 xff09 枚举的初始化 3 xff09 指定枚举类型 4 声明枚举对象 5
  • Qt Q_ENUM使用 枚举字符串互转

    目录 1 简述2 Q ENUM用法2 1 声明使用2 2 测试例子 3 用模板实现一个字符串枚举互转3 1代码3 2 用法示例 1 简述 数据库里用到了枚举的存储 xff0c 比如一个设备有两个状态 xff0c 保持数据库和代码的可读性 x
  • C#中的枚举 Enum和enum的区别

    枚举类型本质上是一个字典 xff0c 它将一组字符串映射到一组整数值 每个枚举常量都具有一个关联的整数值 xff0c 默认情况下 xff0c 第一个枚举常量的值为 0 xff0c 后续枚举常量的值会自动加 1 C 中有两种枚举类型 xff1
  • C++中枚举enum详解

    转载博客地址 xff1a https blog csdn net bruce 0712 article details 54984371 众所周知 xff0c C C 43 43 语言可以使用 define和const创建符号常量 xff0
  • C#中Enum枚举类型的简单使用

    枚举类型的介绍 xff1a 枚举类型是由一组特定常量构成的一组数据结构 xff0c 是值类型的一种特殊形式 xff0c 当需要一个由指定常量集合组成的数据类型时 xff0c 使用枚举类型 枚举声明可以显式地声明 byte sbyte sho
  • C#枚举(Enum)

    枚举是直接在命名空间 类或结构中使用 enum 关键字定义的 所有常量名都可以在大括号内声明 xff0c 并用逗号分隔 下面定义了工作日的枚举 示例 xff1a 定义一个枚举 enum WeekDays Monday Tuesday Wed
  • C++枚举类型enum使用方法(附带可用代码+通俗易懂)

    1 说明 枚举用来表示某类事情的结果 xff1b 例1 xff1a 下棋比赛的三种结果 xff0c 赢 xff0c 和 xff0c 输 xff1b 这里是描述比赛的结果 例2 xff1a 一周7天中的俩种结果 xff0c 工作日和非工作日
  • C++遍历输出enum枚举类型

    enum DAY MON TUE WED THU FRI SAT SUN 问题 如果使用如下方式来遍历 xff0c 则编译器会报类型转换失败错误 xff0c 因为enum类型没有 43 43 运算符 xff0c 也不支持 43 运算 for
  • C++中enum与字符串或CString互相转换的方法

    C 43 43 中没有专门为enum与字符串或CString互相转换的直接方法 xff0c 但是工作中会常遇到相互转换的场景 下面介绍一种自己实现的方法 xff0c 首先得定义一个enum类型 xff0c 同时 xff0c 定义一个与之对应
  • 推荐一个C++枚举转字符串的开源项目magic_enum

    文章目录 前言magic enum简单介绍具体使用原理简述局限性 简化与改进总结 前言 C 43 43 11引入了强类型的枚举类 enum class 用来代替旧风格枚举enum xff0c 新引入的 enum class 具有诸多优点 x
  • TT's Magic Cat -- 差分

    题意 TT 有一只猫 xff0c 它从 世界地图 选了 n 个城市 xff0c 用 ai 表示每个城市的资产 猫会给出几个操作 xff0c 区间 l r 的城市资产都加 c 在q次操作后 xff0c 输出所有城市的资产 Input 第一行有
  • c++打印enum class

    span class token keyword enum span span class token keyword class span span class token class name A span span class tok
  • 【Mybatis】No enum constant org.apache.ibatis.type.JdbcType.LONG

    问题描述 xff1a 今天编写定时任务管理模块 xff0c 提交定时任务实体信息时 xff0c 提示如下错误 nested exception is org apache ibatis builder BuilderException Er
  • 深入理解Java枚举类型(enum)

    版权申明 未经博主同意 xff0c 谢绝转载 xff01 xff08 请尊重原创 xff0c 博主保留追究权 xff09 http blog csdn net javazejian article details 71333103 出自 z
  • C语言--符号常量

    在C语言中 可以用一个标识符来表示一个常量 称之为符号常量 其特点是编译后写在代码区 不可寻址 不可更改 属于指令的一部分 一 符号常量定义用 define 符号常量在使用之前必须先定义 其一般形式为 形式为 define 标识符 常量 e
  • IOS_Swift_enum枚举方法

    本博文为子墨原创 转载请注明出处 http blog csdn net zimo2013 article details 50116811 enum Type Int case A 1 case B 3 普通方法 func toString
  • Java,Enum里定义属性和方法

    最近的项目用到了大神写的统一返回码的代码 ErrorCode java 统一6位 异常码 author Administrator public enum ErrorCode global OK 000000 操作成功 ERROR 0000
  • C# 枚举 enum(学习心得 17)

    枚举是一组命名整型常量 枚举类型是使用 enum 关键字声明的 C 枚举是值类型 枚举包含自己的值 且不能继承或传递继承 超级小白友好 讲解C 基础 每集5分钟轻松学习 拒绝从入门到放弃 声明 enum

随机推荐

  • 一种基于深度学习的方法来检测摩托车头盔的使用

    背景 据统计使用摩托车头盔可以将道路交通事故中摩托车驾驶员致命伤害的可能性降低42 xff05 xff0c 尽管如此 xff0c 遵守摩托车头盔还是较少 xff0c 尤其是在发展中国家 xff0c 为了有效开展针对性的头盔使用运动 xff0
  • 偏振光相机1——偏振光

    光的电磁波属性 光是一种电磁波 xff0c 这个概念大家应该不陌生 既然是电磁波 xff0c 那我们从电磁波的特性上来看它有哪些属性 用图1中的交变电磁场来描述光的特性 xff0c 电场和磁场在空间中相互垂直 xff0c 它们同时与光的传播
  • 偏振光相机2——索尼大法

    Stokes参量 在上一篇 偏振光相机 偏振光 中 xff0c 我们知道偏振光有线性偏振光 椭圆偏振光 圆偏光 那么如何定量的描述偏振光呢 xff1f Stokes矢量是一种广泛用来描述偏振光属性的方法 图1 不同类型的偏振光 线性偏振光和
  • 偏振光相机3——偏振应用

    在之前的2篇中 xff0c 介绍了偏振光的基本概念和基于SONY最新CMOS偏振传感器芯片的相机 在本篇中 xff0c 我们来看看偏振相机的一些应用 偏振相机的应用离不开偏振光 xff0c 那么先看看如何得到偏振光信息 如何获取偏光 在 偏
  • 【干货】生成对抗网络GANs算法在医学图像领域应用总结

    Goodfellow等人 介绍了生成对抗网络 xff08 GAN xff09 以模拟数据分布 由于与两个基本属性相关的原因 xff0c GAN可以合成真实图像 GAN是一种无监督的训练方法 xff0c 可以通过类似于人类学习图像特征的方式获
  • 图像算法之3D人脸识别技术原理概述

    随着深度学习技术的进步 xff0c 面部相关任务的研究也成为学术界和工业界的热门话题 众所周知的面部任务通常包括面部检测 xff0c 面部识别 xff0c 面部表情识别等 xff0c 其主要使用2D RGB面部 xff08 通常包括一些纹理
  • 如何使用OpenCV计算机视觉检测帕金森病图片

    在本教程中 xff0c 您将学习如何使用OpenCV和机器学习在手绘的螺旋和波浪图像中自动检测帕金森病 本教程来自来自巴西的博士生Joao Joao有兴趣利用计算机视觉和机器学习基于几何图形 xff08 即螺旋和符号波 xff09 自动检测
  • OpenCV快速寻找图像差异

    如何使用结构相似性指数 xff08 SSIM xff09 将两个图像与Python进行比较 使用这种方法 xff0c 我们能够轻松确定两个图像是否相同或由于轻微的图像处理 xff0c 压缩伪像或有目的的篡改而产生差异 今天我们将扩展SSIM
  • C++17使用std::optional表示一个可能存在的值

    文章目录 前言返回一个bool值使用 std optional 改写总结 前言 平时写代码会遇到一种传递参数特殊值标记特殊流程 xff0c 或者函数返回值存在魔法数的情况 xff0c 很需要一种标记参数或返回值状态的结构 xff0c 那么在
  • Redhat进程管理

    进程管理 概论 xff1a 程序 xff1a 静态的代码 xff0c 占用磁盘空间 进程 xff1a 动态的代码 xff0c 占用内存 cpu xff08 提供服务的主体 xff09 进程的唯一标识 xff1a PID 编号 父进程 子进程
  • ETCD 高可用集群 Centos7

    ETCD 高可用集群 在本地三台虚拟机以static方式搭建ETCD集群测试环境 xff0c 均为Centos7 一 准备工作 1 主机名及IP 主机名IPvm5192 168 56 10vm6192 168 56 11vm7192 168
  • Python 蓝桥杯 七段码

    一 题目描述 二 题目分析 我使用的是暴力解决 xff0c 因为一共就7位 xff0c 但是容易出现漏算或多算 xff0c 经过很久的找错误和改正才得到答案80 一个较易弄错的问题就是出现3中组合 xff1a abde afcd bcef
  • Java XML转换为JSON XML解析 转换为JSON Java 实现JSON转换为XML json转xml

    Java XML转换为JSON XML解析 转换为JSON Java 实现JSON转换为XML json转xml 一 转换代码 1 XML字符串转换为JSON description XML字符串转换为JSON 64 param strXM
  • 5年的人寿保险 、定期存款 和 基金定投 计划对比

    5年的人寿保险 定期存款 和 基金定投 计划对比 一 5年人寿保险情况 市面上普遍的5年人寿保险 xff0c 预期分红的利息是 4 2 情况 xff0c 实际也存在少分 或者不分红的可能 xff0c 承诺的保本利息在不到2 的情况 既然为保
  • Java8 Optional 类常用方法 Java8 Optional orElse 、orElseGet 、orElseThrow 方法区别

    Java8 Optional 类常用方法 Java8 Optional orElse orElseGet orElseThrow 方法区别 一 概述 Optional 类 xff0c 是Java8 新增加的一个对象容器 主要的功能有 xff
  • Java 以数据流的形式发送数据request Java 数据封装到request中

    Java 以数据流的形式发送数据request Java 数据封装到request中 一 描述 1 在做微信支付结果通知的时候 xff0c 看到一个描述 xff1a 微信会把相关支付结果及用户信息通过数据流的形式发送给商户 xff0c 那么
  • 2023北京旅行计划 2023带父母北京旅行计划

    2023北京旅行计划 2023带父母北京旅行计划 一 概述 2023年开始啦 xff0c 疫情也差不多告别一段落 准备安排父母来我工作的城市 北京 xff0c 旅行一番 xff0c 逛一逛 xff0c 看一看 大致的事项 xff1a 1 体
  • Postman 实现备份数据 Postman恢复数据 postman 导出导入数据 postman 导入导出数据

    Postman 实现备份数据 Postman恢复数据 postman 导出导入数据 postman 导入导出数据 一 需求描述 在使用postman调试接口时 xff0c 若遇到内网的环境 xff0c 无法通过账户同步数据 xff1b 在A
  • Idea 设置打开多个文件 Idea打开多个Tab页 Idea打开多行tab页

    Idea 设置打开多个文件 Idea打开多个Tab页 Idea打开多行tab页 一 情景描述 在使用idea的时候 xff0c 经常会打开多个java文件 xff0c 当打开文件达到一定数量时 xff0c 会出现文件折叠在一起的情况 xff
  • 推荐一个C++枚举转字符串的开源项目magic_enum

    文章目录 前言magic enum简单介绍具体使用原理简述局限性 简化与改进总结 前言 C 43 43 11引入了强类型的枚举类 enum class 用来代替旧风格枚举enum xff0c 新引入的 enum class 具有诸多优点 x