当前位置: 首页 > news >正文

C++实现enum反射,类似magic_enum,支持enum classes

C++实现enum反射,类似magic_enum,支持enum classes

有一个

enum EnumTest { a = 1, b, c };

首先我们想实现

template <typename T, T N>
std::string GetEnumName() {return __PRETTY_FUNCTION__;
}

这样打印

GetEnumName<EnumTest,static_cast<EnumTest>(2)>()

出来的就是

std::string GetEnumName() [with T = EnumTest; T N = b; std::string = std::__cxx11::basic_string<char>]

对于这个字符串,我们只需要知道; T N = 后面跟的内容是啥就实现了我们的目标

但是我们不想像这样把参数写在模板了,而是想用一个函数直接传参

也就是想实现

template <typename T, T N>
std::string GetEnumNameImp() {std::string tmp = __PRETTY_FUNCTION__;auto first = tmp.find("T N = ");first += 6;auto end = tmp.find(";", first);return std::string(tmp, first, end - first);
}template <typename T>
std::string GetEnumName(T n) {return GetEnumNameImp<T,n>();
}

但是这样有问题,因为n是变量,无法传入模板。

那可以考虑这样写:

template <typename T>
std::string GetEnumName(T n) {if (n == 1) return GetEnumNameImp<T, T(1)>();if (n == 2) return GetEnumNameImp<T, T(2)>();if (n == 3) return GetEnumNameImp<T, T(3)>();
}

这样子可以保证传入模板的是常量并且可以动态判断了

到这里我们其实已经可以实现反射了。

但是很显然这个代码有那么一个问题:函数这样只能判断有限个数值,如果有更多数值呢,写无限个if吗

我们需要简化一下这个代码,让它能够自动执行完这么多个if,那么if的开始和结束呢?

没有特别好的方法做判断,我们只能先预定定义好开始和结束,比如Magic Enum 默认定义的就是-128~+128

开始实现代码

首先需要介绍一种模板for循环的小trick

template <int begin, int end, typename F>
typename std::enable_if<begin == end>::type TemplateForLoop(const F &fun) {
fun.template call<begin>();
}
template <int begin, int end, typename F>
typename std::enable_if<begin != end>::type TemplateForLoop(const F &fun) {
fun.template call<begin>();
TemplateForLoop<begin + 1, end>(fun);
}struct TestClass {
template <int N>
void call() const {std::cout << "N=" << N << std::endl;
}
};

在这里使用模板递归调用fun函数,并把begin传入到fun中

使用 TestClass<10,20>(TestClass()); 就会循环打印[10,20]

注意这里的begin和end是左闭右闭的,如果需要左闭右开,可以在begin==end时不执行fun

有了模板for循环,接来下就比较简单了

// enum imp
namespace detail {// Enum value must be greater or equals than G_CONFIG_ENUM_RANGE_MIN. By default
// G_CONFIG_ENUM_RANGE_MIN = -128. If need another min range for all enum types
// by default, redefine the macro G_CONFIG_ENUM_RANGE_MIN.
#if !defined(G_CONFIG_ENUM_RANGE_MIN)
#define G_CONFIG_ENUM_RANGE_MIN -128
#endif// Enum value must be less or equals than G_CONFIG_ENUM_RANGE_MAX. By default
// G_CONFIG_ENUM_RANGE_MAX = 128. If need another max range for all enum types
// by default, redefine the macro G_CONFIG_ENUM_RANGE_MAX.
#if !defined(G_CONFIG_ENUM_RANGE_MAX)
#define G_CONFIG_ENUM_RANGE_MAX 128
#endifstatic_assert(G_CONFIG_ENUM_RANGE_MAX < std::numeric_limits<int>::max(),"G_CONFIG_ENUM_RANGE_MAX must be less than INT_MAX.");static_assert(G_CONFIG_ENUM_RANGE_MIN > std::numeric_limits<int>::min(),"G_CONFIG_ENUM_RANGE_MIN must be greater than INT_MIN.");template <typename T, T N>
inline std::string GetEnumNameImp() {
#if defined(__GNUC__) || defined(__clang__)std::string tmp = __PRETTY_FUNCTION__;auto first = tmp.find("T N = ");first += 6;auto end = tmp.find(";", first);return std::string(tmp, first, end - first);
#elif defined(_MSC_VER)// TODO: add support for msvc
#else
#endif
}template <int begin, int end, typename F>
typename std::enable_if<begin == end>::type TemplateForLoop(const F &fun) {fun.template call<begin>();
}
template <int begin, int end, typename F>
typename std::enable_if<begin != end>::type TemplateForLoop(const F &fun) {fun.template call<begin>();TemplateForLoop<begin + 1, end>(fun);
}template <typename T>
struct GetEnumClass {std::string &str_;int n_;GetEnumClass(int n, std::string &str) : n_(n), str_(str) {}template <int N>void call() const {if (n_ == N) {str_ = detail::GetEnumNameImp<T, T(N)>();}}
};} // detail for enum imptemplate <typename T, int min = G_CONFIG_ENUM_RANGE_MIN,int max = G_CONFIG_ENUM_RANGE_MAX>
inline std::string GetEnumName(T n) {std::string str;gxt::detail::TemplateForLoop<min, max>(gxt::detail::GetEnumClass<T>(static_cast<int>(n), str));if (str.empty()) {throw std::runtime_error("\nenum out of range\n");}return str;
}template <typename T, int min = G_CONFIG_ENUM_RANGE_MIN,int max = G_CONFIG_ENUM_RANGE_MAX>
inline int GetNameEnum(std::string name) {std::string str;for (int i = G_CONFIG_ENUM_RANGE_MIN; i <= G_CONFIG_ENUM_RANGE_MAX; i++) {gxt::detail::TemplateForLoop<G_CONFIG_ENUM_RANGE_MIN,G_CONFIG_ENUM_RANGE_MAX>(gxt::detail::GetEnumClass<T>(static_cast<int>(i), str));if (!str.empty()) {  // solve bug that use class enumauto find = str.find("::");if (find != std::string::npos) {find += 2;str = std::string(str, find);}}if (!str.empty() && str == name) {return i;}}throw std::runtime_error("\nenum out of range\n");return 0;
}

相关文章:

C++实现enum反射,类似magic_enum,支持enum classes

C实现enum反射&#xff0c;类似magic_enum&#xff0c;支持enum classes 有一个 enum EnumTest { a 1, b, c };首先我们想实现 template <typename T, T N> std::string GetEnumName() {return __PRETTY_FUNCTION__; }这样打印 GetEnumName<EnumTest,static_cast…...

机器学习与模式识别作业----决策树属性划分计算

文章目录 1.决策树划分原理1.1.特征选择1--信息增益1.2.特征选择2--信息增益比1.3.特征选择3--基尼系数 2.决策树属性划分计算题2.1.信息增益计算2.2.1.属性1的信息增益计算2.2.2.属性2的信息增益计算2.2.3.属性信息增益比较 2.2.信息增益比计算2.3.基尼系数计算 1.决策树划分原…...

爬虫破解:解决CSRF-Token反爬问题 - 上海市发展和改革委员会

标题:爬虫破解:解决CSRF-Token反爬问题 - 上海市发展和改革委员会 网址:https://fgw.sh.gov.cn/fgw-interaction-front/biz/projectApproval/home MD5加密:ca7f5c978b1809d15a4b228198814253 需求文档 采集数据如下所示: 解决反爬思路 这里只提供解决思路,解决反爬,…...

网络代理技术的威力:保障安全、保护隐私

在如今高度互联的数字时代&#xff0c;网络代理技术正在崭露头角&#xff0c;为网络工程师和普通用户提供了保障网络安全和隐私的强大工具。本文将深入探讨Socks5代理、IP代理以及它们在网络安全、爬虫开发和HTTP协议中的关键作用。 1. Socks5代理&#xff1a;多功能的网络中继…...

【STM32 中断】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 STM32中断 前言一、STM32的中断如何&#xff1f;如何管理这么复杂的中断&#xff1f;实际优先级如下怎么使用呢&#xff1f; 二、使用步骤1.引入库函数先分组&#xff0c;怎么…...

TensorFlow入门(十二、分布式训练)

1、按照并行方式来分 ①模型并行 假设我们有n张GPU,不同的GPU被输入相同的数据,运行同一个模型的不同部分。 在实际训练过程中,如果遇到模型非常庞大,一张GPU不够存储的情况,可以使用模型并行的分布式训练,把模型的不同部分交给不同的GPU负责。这种方式存在一定的弊端:①这种方…...

在React中,什么是props(属性)?如何向组件传递props?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

java 每种设计模式的作用,与应用场景

文章目录 前言java 每种设计模式的作用&#xff0c;与应用场景 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话&#xff0…...

Appium问题及解决:打开Appium可视化界面,点击搜索按钮,提示inspectormoved

打开Appium可视化界面&#xff0c;点击搜索按钮&#xff0c;提示inspectorMoved&#xff0c;那么如何解决这个问题呢&#xff1f; 搜索了之后发现&#xff0c;由于高版本Appium&#xff08;从1.22.0开始&#xff09;的服务和元素查看器分离&#xff0c;所以还需要下载Appium In…...

android 不同进程之间数据传递

1.handler android.os.Message是定义一个Messge包含必要的描述和属性数据&#xff0c;并且此对象可以被发送给android.os.Handler处理。属性字段&#xff1a;arg1、arg2、what、obj、replyTo等&#xff1b;其中arg1和arg2是用来存放整型数据的&#xff1b;what是用来保存消息标…...

一个完整的初学者指南Django-part1

源自&#xff1a;https://simpleisbetterthancomplex.com/series/2017/09/04/a-complete-beginners-guide-to-django-part-1.html 一个完整的初学者指南Django - 第1部分 介绍 今天我将开始一个关于 Django 基础知识的新系列教程。这是一个完整的 Django 初学者指南。材料分为七…...

SpringBoot和Hibernate——如何提高数据库性能

摘要&#xff1a;本文由葡萄城技术团队发布。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 在软件开发领域&#xff0c;性能是重中之重。无论您是构建小型 Web 应用程序还是大型企业系统…...

五分钟Win11安装安卓(Android)子系统

十分钟&#xff0c;完成win11安装安卓子系统 Step1、地区设置为美国 Wini 进入设置页面&#xff0c;选择时间和语言-语言和区域- 区域-美国 Step2 安装 Windows Subsystem for Android™ with Amazon Appstore 访问如下连接&#xff0c;install即可 安卓子系统 Step3 安…...

基于LSTM-Adaboost的电力负荷预测的MATLAB程序

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 主要内容&#xff1a; LSTM-AdaBoost负荷预测模型先通过 AdaBoost集成算法串行训练多个基学习器并计算每个基学习 器的权重系数,接着将各个基学习器的预测结果进行线性组合,生成最终的预测结果。代码中的LST…...

GLTF纹理贴图工具让模型更逼真

1、如何制作逼真的三维模型&#xff1f; 要使三维模型看起来更加逼真&#xff0c;可以考虑以下几个方面&#xff1a; 高质量纹理&#xff1a;使用高分辨率的纹理贴图可以增强模型的细节和真实感。选择适合模型的高质量纹理图像&#xff0c;并确保纹理映射到模型上的UV坐标正确…...

HttpServletResponse对象

1.介绍 在Servlet API中&#xff0c;定义了一个HttpServletResponse接口&#xff0c;它继承自ServletResponse接口&#xff0c;专门用来封装HTTP响应消息。由于HTTP响应消息分为状态行、响应消息头、消息体三部分&#xff0c;因此&#xff0c;在HttpServletResponse接口中定义…...

在SSL中进行交叉熵学习的步骤

在半监督学习&#xff08;Semi-Supervised Learning&#xff0c;SSL&#xff09;中进行交叉熵学习通常包括以下步骤&#xff1a; 准备标注数据和未标注数据 首先&#xff0c;你需要准备带有标签的标注数据和没有标签的未标注数据。标注数据通常是在任务中手动标记的&#xff…...

10月TIOBE榜Java跌出前三!要不我转回C#吧

前言 Java又要完了&#xff0c;又要没了&#xff0c;你没看错&#xff0c;10月编程语言榜单出炉&#xff0c;Java跌出前三&#xff0c;并且即将被C#超越&#xff0c;很多资深人士预测只需两个月&#xff0c;Java就会跌出前五。 看到这样的文章&#xff0c;作为一名Java工程师我…...

优盘中毒了怎么办?资料如何恢复

在现代社会中&#xff0c;优盘成为我们日常生活与工作中必备的便携式存储设备。然而&#xff0c;正是由于其便携性&#xff0c;优盘也成为病毒感染的主要目标之一。本篇文章将帮助读者了解如何应对优盘中毒的情况&#xff0c;以及如何恢复因病毒感染丢失的资料。 ▶优盘为什么…...

如何查看端口占用(windows,linux,mac)

如何查看端口占用&#xff0c;各平台 一、背景 如何查看端口占用&#xff1f;网上很多&#xff0c;但大多直接丢出命令&#xff0c;没有任何解释关于如何查看命令的输出 所谓 “查端口占用”&#xff0c;即查看某个端口是否被某个程序占用&#xff0c;如果有&#xff0c;被哪…...

用Python和Pandas手把手教你计算股票技术指标(MA、MACD、KDJ、RSI、OBV保姆级代码)

用Python和Pandas实现股票技术指标全解析&#xff1a;从数据清洗到策略回测 在量化投资领域&#xff0c;技术指标分析是识别市场趋势、判断买卖时机的重要工具。对于刚接触Python数据分析的投资者来说&#xff0c;如何将教科书上的指标公式转化为可执行的代码往往是个挑战。本文…...

突破本地开发壁垒:tunnelto无缝连接全球网络的技术革新

突破本地开发壁垒&#xff1a;tunnelto无缝连接全球网络的技术革新 【免费下载链接】tunnelto Expose your local web server to the internet with a public URL. 项目地址: https://gitcode.com/GitHub_Trending/tu/tunnelto 痛点诊断&#xff1a;当本地服务成为协作孤…...

听说拍照的人会拿相似的鱼皮豆代替野生鹌鹑蛋拍照(防原创)

听说拍照的人会拿相似的鱼皮豆代替野生鹌鹑蛋拍照&#xff08;防原创&#xff09;大家都知道吃野生动物会得怪病&#xff0c;吃野生植物很容易中毒因为野生植物很多都有毒&#xff0c;获取野生鹌鹑蛋属于盗猎野生动植物破坏野生环境&#xff08;在野外拍摄写生不破坏野生环境除…...

从FAST_LIO到Livox HAP:ROS驱动版本升级中的消息适配实战

1. 当FAST_LIO遇上Livox HAP&#xff1a;问题诊断与场景分析 最近在实验室部署Livox HAP雷达时遇到了一个典型的技术断层问题&#xff1a;最新采购的HAP雷达只支持livox_ros_driver2驱动&#xff0c;而团队长期使用的FAST_LIO算法仍然依赖旧版livox_ros_driver。这就像给最新款…...

【Web前端】深入解析JavaScript异步编程

JavaScript的异步编程是其核心特性之一&#xff0c;也是理解JavaScript运行机制的关键。下面我从几个方面详细介绍。一、为什么需要异步编程&#xff1f;JavaScript 是单线程语言&#xff0c;意味着同一时间只能做一件事。如果没有异步编程&#xff0c;当遇到耗时操作&#xff…...

Windows 10下ISE14.7与Modelsim 10.1c联合安装避坑指南(附完整破解流程)

Windows 10下ISE14.7与Modelsim 10.1c联合安装全流程解析 对于FPGA开发者而言&#xff0c;一套稳定的EDA环境是高效工作的基础。本文将详细介绍如何在Windows 10 64位系统中完成ISE Design Suite 14.7与Modelsim SE 10.1c的联合安装配置&#xff0c;特别针对安装过程中可能遇到…...

5大突破解决Android固件提取难题:面向开发者与技术爱好者的全能工具指南

5大突破解决Android固件提取难题&#xff1a;面向开发者与技术爱好者的全能工具指南 【免费下载链接】Firmware_extractor 项目地址: https://gitcode.com/gh_mirrors/fi/Firmware_extractor 问题引入&#xff1a;Android固件提取的碎片化困境 Android生态系统的开放性…...

LaTeX投稿Elsevier期刊必备:elsarticle.cls从安装到实战避坑指南

LaTeX投稿Elsevier期刊必备&#xff1a;elsarticle.cls从安装到实战避坑指南 科研工作者向Elsevier投稿时&#xff0c;elsarticle.cls文档类是最常用的工具之一。不同于基础教程&#xff0c;本文将聚焦实际投稿过程中的高频痛点&#xff0c;从环境配置到排版细节&#xff0c;提…...

通信与导航-技术博客网站上线了-正式

通信与导航-技术博客网站上线了 自2025年3月开始在微信公众号写通信与导航相关技术文章以来&#xff0c;至今已经过11个月。在公众号平台上&#xff0c;积累了相当数量的粉丝&#xff0c;获得了平台的流量推荐&#xff0c;还通过公众号结识了许多业内朋友&#xff0c;线下对接了…...

nomic-embed-text-v2-moe部署教程:Nginx反向代理+HTTPS配置保障生产环境安全

nomic-embed-text-v2-moe部署教程&#xff1a;Nginx反向代理HTTPS配置保障生产环境安全 1. 开篇&#xff1a;为什么你的AI模型需要一个“门卫”&#xff1f; 想象一下&#xff0c;你刚把一台功能强大的AI服务器部署在公司内网&#xff0c;准备用它来处理各种文本分析任务。结…...