跟我学c++高级篇——动态反射之一遍历

一、动态反射

前面讲一篇静态反射,今天在这个基础上对动态反射进行一下入门。动态反射前面提到过,一般是指在运行时动态获取类型或者生成实例。那么如何才能动态获得类型呢?方法有很多种,下面从最简单的开始。

二、入门程序

动态反射的一个简单例子如下:

#include <tuple>
#include <string>
#include <unordered_map>
#include <iostream>enum class RgbColor {RGB_RED,RGB_BLACK,RGB_WHITE,NOTHING};std::tuple<std::string, std::string, std::string> tDesc = {"red","black","white"};
std::unordered_map<std::string, RgbColor> mapColor = { {"red",RgbColor::RGB_RED},{"black",RgbColor::RGB_BLACK},{"white",RgbColor::RGB_WHITE}};RgbColor strToType(const std::string& color)
{auto num = mapColor.count(color);if (num > 0) {return mapColor[color];}else {return RgbColor::NOTHING;}
}void GetColorTest(const std::string&str)
{auto color = strToType(str);std::cout << "str is:" << str << "," << "Color is:" << static_cast<int>(color) << std::endl;
}

但是这么做除了麻烦外还容易出错。另外为了一个简单的反射,写了如此多的不可重用的代码确实也让人觉得有点低效。

三、使用__PRETTY_FUNCTION__

其实动态反射的核心在动态类型的获取,那么可以在前面使用__PRETTY_FUNCTION__的基础上对其进行处理,从而使其可以在运行获取对象的类型:

#include <iostream>
#include <string>#ifdef _WIN64
#define __FUNC__ __FUNCSIG__
#else
#define __FUNC__  __PRETTY_FUNCTION__
#endifenum class DataType{USB,PCI,HD};
enum  DType{USB,PCI,HD};
template<auto T>
auto TypeInfo()
{std::string type = __FUNC__;auto s = type.find("T = ") + 4;auto e = type.find_last_of(']');return std::string_view{ type.data() + s, e - s };
}template<typename T>
std::string_view Typeof(T t)
{int t1 = static_cast<int>(t);if (t1 == 0){return TypeInfo<DataType::USB>();}if (t1 == 1){return TypeInfo<DataType::PCI>();}if (t1 == 2){return TypeInfo<DataType::HD>();}return std::string_view("");
}void getTypeTest()
{std::cout << Typeof(DataType::HD) << std::endl;std::cout << Typeof<DType>(DType::PCI) << std::endl;
}int main()
{getTypeTest();return 0;
}

上面这些代码其实和最初的代码不同点在于他可以动态的适应名称的变化和相关内容的增加而不需要增加代码的编写和维护。可是上面的代码还是有些麻烦,比如枚举的值不断的增加,那么if语句就这么一直增加下去么?可行是可行的,但有点不爽,可以写成下面的形式:

#include <iostream>
#include <string>
#include <type_traits>#ifdef _WIN64
#define __FUNC__ __FUNCSIG__
#else
#define __FUNC__  __PRETTY_FUNCTION__
#endifenum class DataType{USB,PCI,HD,NOT};
enum  DType{USB,PCI,HD,NOT};
template<auto T>auto TypeInfo()
{std::string type = __FUNC__;auto begin = type.find("T = ") + 4;auto end = type.find_last_of(']');return std::string_view{ type.data() + begin, end - begin };
}template <int s, int e>
struct static_for
{template<typename F>void operator()(const F& func) const{if (s < e){//注意:一定要转成常量func(std::integral_constant<int,s>());static_for<s + 1, e>()(func);}}
};template <int n>
struct static_for<n, n>
{template<typename F>void operator()( const F & func) const{// std::cout << "noting" << std::endl;}
};
constexpr int s = static_cast<int>(DataType::USB);
constexpr int e = static_cast<int>(DataType::NOT);template<typename T>
std::string_view Typeof(T t)
{int t1 = static_cast<int>(t);std::string_view sv;static_for<s, e>()([&](auto num) {if (t1 == num) {//重点要理解const和num.valueconst DataType d = DataType{num.value};sv = TypeInfo<d>();}});return sv;
}void getTypeTest()
{std::cout << Typeof(DataType::HD) << std::endl;//std::cout << Typeof<DType>(DType::PCI) << std::endl;
}int main()
{getTypeTest();return 0;
}

使用了一个static_for,它的实现方式有很多种,这里用的是类似变参模板的递归方式,也可以使用条件判断的方式,也可以直接写到一个模板函数中,都可以实现类似的方式。重点是需要它展开模板,实现类似循环即可。

四、总结

这篇内容就有点接近正常理解的反射的意思了,本来这篇想把一个动态表生成的方式也分析了,但是又觉得太长了,还是分到下一篇再一起分享。慢慢来,不要急。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/190788.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于运算放大器的电压采集电路

一、运算放大器 运放推导的两个重要概念&#xff1a;虚短、虚断。 1、差分放大器 以差分放大器为例进行推导分析。 虚断–运放的"-“端、”“端的引脚电流接近为0&#xff1b; 根据基尔霍夫电流定律可知&#xff1a;iR1iRF&#xff0c;iR2iR3&#xff1b; iR1(Ui1-(V-…

C语言结构体详解(一)(能看懂文字就能明白系列)

&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;个人主页&#xff1a; 古德猫宁- &#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;…

简单聊聊更快、更稳、更高效的 QUIC 协议

目录 QUIC的起源和发展 QUIC 与 TCP 和 UDP 的比较 QUIC 的主要特性 QUIC 的工作原理 QUIC 的应用场景 小结 QUIC&#xff08;Quick UDP Internet Connections&#xff0c;快速 UDP 互联网连接&#xff09;是一种基于 UDP 协议的传输层协议&#xff0c;由 Google 首次提出…

上个班而已

习惯性刷CSDN&#xff0c;发现了这么个主题&#xff0c;有意思。在我的字典里&#xff0c;“养生”这个条目已经被我删了。看过了太多的伪科学、贩卖焦虑、带货、自以为是&#xff0c;干脆眼不见为净。但程序员人均亚健康这句话真未必是个玩笑&#xff0c;所以还是凑个热闹聊上…

XML Schema中的elementFormDefault

XML Schema中的elementFormDefault&#xff0c;用以指明xml的元素是否必须有命名空间的前缀。 它的取值可以为qualified、或者unqualified。默认值为unqualified。 当取值为qualified时&#xff0c;xml元素前必须有命名空间作为前缀&#xff1b; 当取值为unqualified时&#x…

04.PostgreSQL是如何实现隔离级别的?

PostgreSQL是如何实现隔离级别的&#xff1f; 事务有哪些特性&#xff1f; 事务看起来感觉简单&#xff0c;但是要实现事务必须要遵守 4 个特性&#xff0c;分别如下&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a;一个事务中的所有操作&#xff0c;要么…

Istio新架构揭秘:环境化Mesh

自问世以来&#xff0c;Istio因其使用Sidecar&#xff08;可编程代理与应用容器一同部署&#xff09;而备受认可。这种架构选择使Istio用户能够享受其好处&#xff0c;而无需对其应用进行 drast 改变。这些可编程代理&#xff0c;与应用容器紧密部署在一起&#xff0c;因其能够…

CC++枚举类型与类型定义(typedef)

在C中&#xff0c;枚举类型&#xff08;enum&#xff09;和类型定义&#xff08;typedef&#xff09;都是用来为数据类型创建别名的机制。它们可以提高代码的可读性和维护性。 枚举类型&#xff08;enum&#xff09; 枚举类型是一种用户自定义的数据类型&#xff0c;用于定义…

java学习part27线程死锁

基本就是操作系统的内容 138-多线程-线程安全的懒汉式_死锁_ReentrantLock的使用_哔哩哔哩_bilibili

【大模型】更强的 ChatGLM3-6B 来了,开源可商用

【大模型】更强的 ChatGLM3-6B 来了&#xff0c;开源可商用 简介ChatGLM3-6B 环境配置环境搭建安装依赖 代码及模型权重拉取拉取 ChatGLM3-6B拉取 ChatGLM3-6B 模型权重及代码 终端测试网页测试安装 gradio加载模型并启动服务 参考 简介 ChatGLM3-6B ChatGLM3-6B 是 ChatGLM …

总结 SpringMVC 中的常用注解和用法

RequestMapping ??是?Spring?Web?MVC?应⽤程序中最常被⽤到的注解之⼀&#xff0c;它是⽤来注册接⼝的 路由映射的.? 表⽰服务收到请求时,?路径为?/sayHi?的请求就会调⽤?sayHi?这个⽅法的代码.?? 路由映射:?当⽤⼾访问⼀个?URL?时,?将⽤⼾的请求对应到程序中…

thinkphp控制器调用脚本

一、同步方式 //脚本配置示例protected function configure(){// 指令配置$this->setName(pltUpgrade)->addArgument(type, Argument::OPTIONAL, your type)->addOption(id, null, Option::VALUE_REQUIRED, upgrade id)->setDescription(PltUpgrade);}// 调用命令行…

基于STM32的四轴飞行器的控制系统(论文+源码)

1.系统设计 本次基于stm32单片机的四轴飞行器控制系统主要包括硬件和软件这两大部分&#xff0c;其中硬件部分是基于单片机的四轴飞行器控制系统实现的基石&#xff0c;其中主要STM32单片机负责整个系统功能的实现&#xff1b;NRF24L01无线模块负责对四轴飞行器的远程控制&…

rtmp 协议详解

1. handshake 1.1 概述 rtmp 连接从握手开始。它包含三个固定大小的块。客户端发送的三个块命名为 C0,C1,C2&#xff1b;服务端发送的三个块命名为 S0,S1,S2。 握手序列&#xff1a; 客户端通过发送 C0 和 C1 消息来启动握手过程。客户端必须接收到 S1 消息&#xff0c;然后…

MS721仪表总线收发器可Pin to Pin兼容TSS721A

MS721 是为 M-Bus 标准&#xff08;EN1434-3&#xff09;的应用而开发的单片收发电路。MS721 接口电路可以适应从站与主站之间的电压差&#xff0c;总线的连接没有极性要求&#xff0c;电路由主站通过总线供电&#xff0c;这样对于从站电池就不会增加额外的负载&#xff0c;同时…

轻量级万物分割SAM模型——MobileSAM安装实测摘要

目录 0、前言1、准备工作安装python环境说明安装说明 运行测试app安装依赖修改代码 2、实际测试效果自带图片测试其它图片测试1其它图片测试2 总结 0、前言 本文将介绍一种轻量级万物分割SAM模型——MobileSAM的安装和实测情况。SAM是meta公司的一种图像分割大模型&#xff0c…

二分+dp:[ARC120E] 1D Party

https://www.luogu.com.cn/problem/AT_arc120_e 考虑二分时间&#xff0c;然后设 d p ( i , 0 ) dp(i,0) dp(i,0) 表示第 i i i 个人开头往左走&#xff0c;掉头后剩余步数。 d p ( i , 1 ) dp(i,1) dp(i,1) 表示第 i i i 个人先往右走&#xff0c;最多走多少步就有掉头。 …

css中的 Grid 布局

flex布局和grid布局区别 flex布局是 一维布局grid布局是二维布局 flex布局示例 grid布局示例 grid 布局初体验 体验地址 <div class"wrapper"><div class"one item">One</div><div class"two item">Two</div&…

Asp.net core WebApi 配置自定义swaggerUI和中文注释,Jwt Bearer配置

1.创建asp.net core webApi项目 默认会引入swagger的Nuget包 <PackageReference Include"Swashbuckle.AspNetCore" Version"6.2.3" />2.配置基本信息和中文注释&#xff08;默认是没有中文注释的&#xff09; 2.1创建一个新的controller using Micr…

开源堡垒机Jumpserver

文章目录 开源堡垒机JumpserverJumpserver介绍安装环境部署安装jumpserver访问jumpserver的web界面 开源堡垒机Jumpserver Jumpserver介绍 Jumpserver 是全球首款完全开源的堡垒机&#xff0c;使用 GNU GPL v2.0 开源协议&#xff0c;是符合 4A 的运维安全审计系统。 Jumpse…