C/C++ 人们自行构建高性能反射框架,应该怎么设计比较好。

在 C/C++ 之中默认提供的 “RTTI” 运行时类型信息反射机制过于脆弱,基本就等于没什么卵用,但在 C/C++ 11 之前模板元编程不是那么强大的时候,还是有那么一点点作用。

我们通常利用RTTI反射T的类型或其泛型类型(即T的T)(字符串,缩写形式)根据类型的判断来调用对应的特例实现,但是用的不多,在C/C++ 11及以上版本之中,实战的用处基本就等于没有了。
 

但是我们希望实现一个没那么强大的类型反射系统,可以获取、设置属性、调用方法的话,其实也是有一些办法的。

本文简单的例子,不代表需要去构造完整的框架链,只是让大家知道,C/C++ 应该怎么做反射框架,就像有些博主教 C/C++ 怎么做GC自动垃圾回收系统是一样的。

C/C++ 什么都可以办到,这么强大的中高级语言编程工具,不能只是写点 Simple 无涵养的业务逻辑代码,喜欢做搬砖的杂活,Java、Go 语言会是很好的一个选择。

本文将实现一个简单反射读取、修改结构体的成员字段的示例程式:

玩家们可以不选择我们这种实现形式,方法有很多,比如:nlohmann / json 实现RTTI反射框架的形式,也挺有一些意思的。

调用本文做的反射读写字段小例子:

int main(int argc, const char* argv[]) noexcept
{Foo foo;foo.x = 200;foo.y = 100;std::unordered_map<std::string, int>& fields = Foo::__RTTI__::c().__rtti_field;RTTI_SetField(fields, &foo, "x", 300);RTTI_SetField(fields, &foo, "y", 400);std::cout << "x: " << RTTI_GetField(fields, &foo, "x", 0) << " y: " << RTTI_GetField(fields, &foo, "y", 0) << std::endl;
}

实现 C/C++ 结构类成员字段反射:

#define RTTI_FILED(var) __rtti_field[#var] = offset_of(_Ty, var);
#define RTTI_S(T)                                       \
struct __RTTI__ {                                       \typedef T                                      _Ty; \\std::unordered_map<std::string, int> __rtti_field;  \\static __RTTI__& c() {                              \static __RTTI__ r;                              \return r;                                       \}                                                   \\__RTTI__() {                                        #define RTTI_E                                          \}                                                   \
};struct Foo {int x;int y;RTTI_S(Foo);RTTI_FILED(x);RTTI_FILED(y);RTTI_E;
};template <typename T, typename TValue>
bool RTTI_SetField(std::unordered_map<std::string, int>& fields, T* obj, const std::string& method, TValue value) {auto tail = fields.find(method);auto endl = fields.end();if (tail == endl) {return false;}*(TValue*)((char*)obj + tail->second) = value;return true;
}template <typename T, typename TValue>
TValue RTTI_GetField(std::unordered_map<std::string, int>& fields, T* obj, const std::string& method, TValue deafult_value) {auto tail = fields.find(method);auto endl = fields.end();if (tail == endl) {return deafult_value;}return *(TValue*)((char*)obj + tail->second);
}

宏函数:(依赖)

查看本人该篇博文;

C/C++ 11 offsetof、container_of 宏函数的实现(无限制编译器)_c++ 11 container_of-CSDN博客

我们可以利用宏编程,在每个侵入的结构体类之中构造其成员(字段、函数)的反射信息,这个 C/C++ 框架做起来并不困难。

或者把存储结构体元数据的信息放在全局存储也可以,通过模板泛型类型T来捕获元数据信息就可以。

对于字段类设置值的话,有两种办法:

1、向本文这样计算字段在内存之中的偏移量

2、利用宏编程来完成 get、set 属性访问器的实现

函数调用这个也不困难的,

C++ 11 提供的可变参数模板,自己调用转发就好了,就是需要注意:返回值为 void 类型还是有值类型的。

最简单的做法是分一个 Call_Void 函数出来,一个 Call 带返回值的函数出来,当然 C/C++ 相当专业的做法显然是模板元编程咯,在 C/C++ 17 上面更容易处理,在 C/C++ 11 ~ 14 上面就需要注意下这些小问题。

都差不多,效率都挺OK,C/C++ 之中自己设计并且构造RTTI系统,只要不是SX玩意,乱整一通,基本上RTTI反射执行效率都是快到飞起滴。

当然有一些想当秀技术的也行,我之前看过一个开源项目,那个只有一个宏,把类型、字段、成员都在这个可变参数宏之中传递进去,然后大量通过 C/C++ 编译器模板元编程来处理。

项目的作者 C/C++ 水平相当秀儿,但大家在自己做 RTTI C/C++ 反射框架的时候大可不必这么秀技术水平,因为模板元编程虽好,但是过于多会导致编译器占用极大的设备内存,编译速度慢到飞起,能一定稳定编译过算运气好。

编译器内存OOM导致崩溃的问题,相信不少搞 C/C++ 的童靴应该都有遇到过,当模板过于复杂的时候,编译器编译一个CPP展开代码过多就有可能导致编译直接OOM炸掉故而编译失败。

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

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

相关文章

数学建模-多目标规划算法(美赛建模)

单目标优化的情况下&#xff0c;只有一个目标&#xff0c;任何两解都可以依据单一目标比较其好坏&#xff0c;可以得出没有争议的最优解。 多目标化与传统的单目标优化相对。多目标优化的概念是在某个情景中在需要达到多个目标时&#xff0c;由于容易存在目标间的内在冲突&…

7 BUILD.gn文件怎么写,Gn + Ninja编译一个Hello world程序的例子Demo

BUILD.gn文件怎么写&#xff0c;Gn Ninja编译一个Hello world程序的例子Demo 作者将狼才鲸创建日期2024-03-11 Ninja安装流程见&#xff1a;一个能直接运行的Ninja例子&#xff0c;build.ninja文件怎么写&#xff1f;Gn安装流程见&#xff1a;Ubuntu18.04下安装Gn软件 这是一…

webpack如何去自定义一个Loader?(大白话,so easy!)

文章目录 关注小白菜&#xff0c;前端变更菜&#xff0c;不定期更新csdn&#xff0c;内容不定看心情随便写点&#xff0c;因为近期在面试&#xff0c;所以整理一下写点笔记&#xff0c;希望可以帮到初中级的同学们&#xff0c;加油&#xff0c;奥里给&#xff01;&#xff01;&…

生成验证码图片

引入依赖包 <!-- 图形验证码 --> <dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version> </dependency> 配置DefaultKaptcha类 类方法配置了验证码的生成格式…

目标检测数据集:手机顶盖焊缺陷检测数据集

✨✨✨✨✨✨目标检测数据集✨✨✨✨✨✨ 本专栏提供各种场景的数据集,主要聚焦:工业缺陷检测数据集、小目标数据集、遥感数据集、红外小目标数据集,该专栏的数据集会在多个专栏进行验证,在多个数据集进行验证mAP涨点明显,尤其是小目标、遮挡物精度提升明显的数据集会在该…

std::thread 的构造-源码解析

std::thread 的构造-源码解析 我们这单章是为了专门解释一下 std::thread 是如何构造的&#xff0c;是如何创建线程传递参数的&#xff0c;让你彻底了解这个类。 我们以 MSVC 实现的 std::thread 代码进行讲解。 std::thread 的数据成员 了解一个庞大的类&#xff0c;最简单…

Anaconda环境全局环境手动配置

Anaconda环境全局环境手动配置 如图&#xff0c;在本机就有Anaconda的情况下&#xff0c;普通cmd无法直接使用conda命令&#xff0c;每次都要从Anaconda Prompt窗口操作&#xff0c;挺不方便的&#xff0c;遂决定进行全局环境配置&#xff0c;记录一下流程。 找到环境配置页面…

R语言绘制散点密度图ggdentity

使用R语言绘制二维密度图 下图是一张常见的二维核密度散点图&#xff0c;能够清晰直观的反映出数据之间的分布趋势&#xff0c;颜色越红的位置数据越集中分布。今天分享的笔记是在R语言中绘制该图的两种常见方法&#xff0c;提供过程代码。 论文中常见的这种展示两组数据之间分…

Java入门学习(1)

常用的CMD命令&#xff1a; 1.盘符名称 冒号 说明&#xff1a;盘符切换&#xff1b; 举例&#xff1a;E:回车&#xff0c;表示切换到E盘。 2.dir 说明&#xff1a;查看当前路径下的内容。 3.cd 说明&#xff1a;进入单级目录。 举例&#xff1a;cd itheima 4.cd.. 说…

上班族必备技能!轻松掌握excel文件如何批量加后缀名方法,提升工作效率!

后缀名是什么 后缀名是帮助人区分文件类型的一种手段&#xff0c;文件后缀名也叫文件扩展名&#xff0c;是用来表示某种文件格式所采用的机制。文件扩展名是加在主文件名后面的&#xff0c;用“.”分隔。不同的软件要求不同的文件格式&#xff0c;后缀名可以帮助用户了解文件是…

可以作为GC.Roots的对象有哪些?

在Java中&#xff0c;GC Roots 是一组特殊的对象&#xff0c;它们被认为是可达的&#xff0c;并且不会被垃圾收集器回收。这些对象包括但不限于以下几种&#xff1a; 虚拟机栈中引用的对象&#xff1a;活跃线程中的本地变量引用的对象&#xff0c;以及正在执行的方法中的参数对…

Python 可视化和数据缺失处理库之missingno使用详解

概要 在数据分析和数据科学的领域中,数据缺失是一个常见的问题。数据缺失可能会导致分析和建模结果的不准确性,因此了解如何处理和可视化缺失数据至关重要。Python Missingno 是一个强大的工具,可以直观地识别和处理数据中的缺失值。本文将详细介绍 Python Missingno 的功能…

从命令提示窗口使用 Visual C++ Toolkit 2003

从命令提示窗口使用 Visual C Toolkit 2003 发布日期 : 12/20/2004 | 更新日期 : 12/20/2004 Brian Johnson MSDN Visual C 内容战略家 适用于&#xff1a; Visual Studio .NET 2003 Microsoft Visual C .NET 2003 Microsoft Visual C Toolkit 2003 摘要&#xff1a;在本文中…

Threejs播放模型自带动画

现在的很多建模软件都可以制作动画效果&#xff0c;甚至可以通过各种动画效果直接做动漫&#xff0c;动漫是模型的一种属性&#xff0c;在threejs中同样可以加载此动画&#xff0c;实现动画效果&#xff0c;如果有的时候在threejs中用代码实现模型动画比较困难或者麻烦&#xf…

MongoDB聚合运算符:$denseRank

$denseRank聚合运算符返回在$setWindowFields阶段分区中文档的排名&#xff0c;排名的顺序由$setWindowFields阶段sortBy的字段值决定。 语法 { $denseRank: { } }$denseRank不需要任何参数。 使用 $rank和$denseRank的不同点在于他们处理排序字段重复值的方式不同&#xf…

嵌入式、开发板 智能音响 OpenHarmony GPT 大模型 智能硬件

一、概述 生活场景的引入: 物联网的快速发展,各种智能设备层出不穷,作为极客,家里早已安上了用 APP 控制的智能灯、智能插座,刚刚安装上的时候,还有新鲜感,久了之后,是不是会有这样的现象: 早上醒来要开灯,需要经过: 迷迷糊糊从床头柜上摸到手机手机用指纹解锁连接无…

3.11 log | 739. 每日温度,

739. 每日温度&#xff0c;496.下一个更大元素 I&#xff0c;503.下一个更大元素II&#xff0c; class Solution { public:vector<int> dailyTemperatures(vector<int>& temperatures) {stack<int> st;vector<int> result(temperatures.size(),0)…

Hadoop学习1:概述、单体搭建、伪分布式搭建

文章目录 概述基础知识Hadoop组件构成Hadoop配置文件 环境准备配置Hadoop配置下载配置环境变量 Hadoop运行模式Standalone Operation&#xff08;本地&#xff09;官方DemoWordCount单词统计Demo Pseudo-Distributed Operation&#xff08;伪分布式模式&#xff09;配置修改启动…

Bootstrap5(display显示、flex布局相关属性、浮动、定位、文本、栅格系统)

类中缀的设置技巧 1.当多个连续品目使用一个样式时&#xff0c;则给最小的设置即可。 比如&#xff1a;大屏以上内边距都是3&#xff1a;p-lh-3 2.超小屏不设置类中缀的样式 比如超小屏内边距时1&#xff0c;小屏内边距时2&#xff0c;中屏及以上内边距是3 p-1 p-sm-2 p-md-3 …

WPF 界面刷新问题 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改

WPF 界面刷新问题 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改 问题描述&#xff1a; 在子线程中操作界面控件的数据源出现以下错误&#xff1a;System.NotSupportedException:“该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCo…