当前位置: 首页 > 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;被哪…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...