跟我学c++高级篇——常见的反射框架

C++实现反射---RTTR库的使用 使用过C#或者Java 的童鞋,应该对这些语言提供的反射机制有所了解。所谓反射,在我看来就是在只知道一个类的名字(字符串形式)的情况下,自动创建出具体的类实例,并且能够枚举该类型拥有的属性、方法等信息。使用反射写出来的代码可以做到异常的精致简洁。 由于我们最近开发的产品使用的是C++语言,然而这种语言并没有内置反射这种机制。于是从网上进行了调研,发现了一些不错的提供C++反射支持的库,如CPP- 阅读详情
AI摘要

本文介绍了C++中的几种开源反射框架,如magic_enum用于枚举反射,Boost.PFR支持动态属性访问,RTTR提供全面的反射功能。作者强调理解反射原理并结合实际场景是编写高效框架的关键。

一、反射框架介绍

在前面基本已经把基础的反射分析了一遍,通过这些学习,已经可以知道C++中反射的特点在哪里。他山之石,可以攻玉,在本篇就结合在网上的一些开源的反射框架来对反射加深一下印象。
目前开源的c++反射框架中,各种类型的都有,复杂的简单的,针对具体类型的和通用的。一般来说,大厂和国外的开源写得相对要好一些,但不是说个人写的就不好,个人一般很多都是自己针对自己的具体场景,所以可能通用性差一些。另外可能个人的编程水平也参差不齐可能有些代码看上去不好,但重要的不是这些,是要看其实现机制和手段是否有可取之处,鲁迅先生的“拿来主义”要学会。
目前常见的c++反射库,一般比较好的有CLANG提供的工具,Boost.Reflection即Boost.PFR,Qt,谷歌的protobuf也可以用来实现反射。另外一些小有名气开源框架有magic_enum(针对枚举)和动态运行时反射的RTTR等。这些都可以在github上找到源码。
在github上还有很多的开源的反射库,大家在掌握了反射的原理和相关的机制后就可以去学习和参考其代码,舍短取长,融汇贯通,写出自己一个反射框架(库)。

二、magic_enum

在网上有开源的一个框架magic_enum,可以搞定枚举的反射,它其实就使用前一篇中所述的__PRETTY_FUNCTION__ 来实现的,这里不多做赘述,只给一个简单的例子:

#include "include/magic_enum/magic_enum.hpp"

enum class RgbColor {RGB_RED,RGB_BLACK,RGB_WHITE,NOTHING};
void GetColorMagic(const std::string& str)
{
	RgbColor rgb = RgbColor::RGB_BLACK;
	std::cout << "rgb value:" << static_cast<int>(rgb) << ",rgb name:" << magic_enum::enum_name(rgb) << std::endl;
}

这个框架针对枚举功能相当强大,许多详细的例程都在框架上有介绍,这里只简单的举一个例子,有兴趣可以更好的学习一下。

三、Boost.Reflection(PFR)

boost.PFR是一个动态运行时反射机制的库,和c++的反射一样,仍然是比较弱小的,但还是在一些情况下可以起到不错的效果:

struct Ex {
  char a;
  float b;
};

void getVar(){
	Ex var{};
	boost::pfr::get<1>(var) = 1.2;

	std::cout << var.b << std::endl;
}
//获得属性数量

struct Ex {
  int a;
	int b;
	int c;
};

std::cout << boost::pfr::tuple_size<Ex>::value << std::endl;

同样在使用这个库时,需要有一些限制,比如不能有虚拟函数,不能对限制属性进行操作。但相对于其它库,它的平台适应性好,应用起来也相对文件。对普通的类的动态创建、函数和属性的反射控制、类型信息处理以及序列化都有可圈可点之处。

四、RTTR

RTTR,Run Time Type Reflection也是一个开源的动态运行时的c++反射库,它的功能基本就是反射的那一套,类型反射,名称反射控制,动态创建对象和控制,安全异常信息检查以及序列化等,它的优点在于他提供了与其它框架的集成如Qt、Boost和STL等。


class Data {
public:
    Data(int d)
        :d_(a){}
    void Display()  {
        std::cout <<  "data is:" << d_  << std::endl;
    }
private:
    int d_;
};

RTTR_REGISTRATION
{
    registration::class_<Data>("Data")
        .constructor<int>()
        .method("Display", &Data::Display);
}

void test() {
    type t = type::get_by_name("Data");
    if (t.is_valid()) {
        std::cout << "get methods: " << t.get_method_count() << std::endl;

        variant dt = t.create(6);
        if (dt.is_valid()) {
            dt.invoke("Display");
        }
    }

    return 0;
}

这个框架库还是不错的,有兴趣可以自己试试。

五、总结

Qt和libclang的使用比较官方化,这个大家就自己理解应用去就可以了,这里就不再一一列举。从这些开源框架的分析介绍可以看出,其实原理和前面的反射方式基本的形式都是一样的。要想写一个好的反射框架,重点是要把C++的技术知识融合起来。“一招鲜,吃遍天”,其实就是这个道理。要想“鲜”,就得把基础打好。有了基础,才是有源之水,才有可能把它们整合起来,才可能“一招鲜”。

C++中boost库的pfr模块是一个增强型结构体反射库,可以使得用户不需要手动定义多少成员变量,就可以快速便捷地操作结构体中的成员变量 C++中boost库的pfr模块是一个增强型结构体反射库,可以使得用户不需要手动定义多少成员变量,就可以快速便捷地操作结构体中的成员变量。在使用pfr模块时,需要了解其中一些关键的函数,如fields_count,我们本篇文章就来介绍如何测试这个函数。首先,为了理解这个测试程序的意义,我们需要知道fields_count函数的用途:它用于获取结构体中的成员变量数量。因此,测试程序的主要目的就是检验该函数的正确性。最后,值得一提的是,由于pfr模块基于C++14标准,因此在编译时需要开启C++14支持。 阅读详情

相关推荐

反射:C ++ 14反射库

反射:C ++ 14反射库

C++ Boost.Reflection库(现在是Boost.PFR)的下载、安装、使用详细教程

Boost.Reflection(现在是Boost.PFR)是一个用于C++的开源库,它提供了一种运行时反射机制。这个库可以让程序在运行时动态地查询、访问类和对象的结构信息,例如类的成员函数、属性、父类等等。通过这些功能,Boost.Reflection可以帮助开发者编写更加灵活、可扩展的代码。

Lion_Long的博客 3197

企业级智能问数开发的核心痛点与技术聚焦

本文介绍了企业级智能问数系统开发的三大核心问题和解决方案:语义解析不精准、SQL生成不健壮、企业适配难落地。文章从开发者视角出发,详细拆解了NLU语义解析、SQL生成、对话记忆、企业级适配四大核心模块的技术实现。 在技术选型方面,推荐了LangChain+DeepSeek-R1、FAISS/Milvus、SQLAlchemy等工具链组合。针对企业级需求,重点讲解了: 语义解析模块的意图识别优化和要素提取技术 SQL生成模块的语法校验与性能优化方案 对话记忆模块的Redis存储实现 企业级适配的三层防护体系和

lamehsl的专栏 1046

C++ 反射库Ponder源码剖析(1)

源码分析

Runner的博客 2720

按照autoware.universe官方从零搭建自己的自动导航小车(三)(续)

本文介绍了在Autoware框架下完善自定义传感器套件描述包的详细过程。主要内容包括:1)创建传感器描述包tinyplc_sensor_kit_description,包含YAML标定文件和URDF模型;2)配置传感器与车辆基座的相对位姿,实现sensor_kit.xacro和sensors.xacro宏文件;3)更新sensor_kit.launch.xml文件以集成激光雷达和GNSS/IMU驱动。通过xacro验证URDF模型正确性后,下一步计划接入Helios16激光雷达数据并在Rviz2中验证点云显

qq_45335326的博客 1272

AI提示词实战:用EARS语法5步搞定产品需求拆解(附完整案例)

本文详细介绍了如何运用EARS语法将模糊的产品需求进行原子化拆解,转化为清晰、可执行的结构化指令。通过一个完整的自由职业者项目管理工具案例,演示了从原始需求分析到构建增强AI提示词的五步实战流程,帮助产品经理和技术人员实现高效、精准的需求传达与协作。

nokia的博客 1029

【使用Boost的C++反射】(来源于stackoverflow回答翻译)

您需要做的是让预处理器生成有关字段的反射数据。此数据可以存储为嵌套类。 首先,为了使它更容易和更干净地在预处理器中编写它,我们将使用类型化表达式。类型化表达式只是将类型放在括号中的表达式。因此,您将编写(int) x,而不是写入int x。下面是一些方便的宏,可帮助使用类型化表达式: #define REM(...) __VA_ARGS__ #define EAT(...) // Retrieve the type #define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYP

hggqiang_phone的博客 1956

WebDriverAgent 菜鸟解析篇

WebDriverAgent 是一个用于模拟移动设备浏览器的 Python 库,可以用来在 PC 上模拟移动设备的浏览器操作,从而进行自动化测试。下面是一个菜鸟对 WebDriverAgent 源码的解析篇,希望能对初学者有所帮助。

DJ355的博客 1220

跟我学c++高级篇——反射

其实反射也可以放到模板元编程中来进行分析,但是为了更好的讲解一些c++的高级特性,还是把它分离了出来。c++的许多高级的特性,在国内的大多数应用场景上,其实是应用不到的。原因是,这些高级特性大多是在基础库支持或者基础软件上才用的。而这恰恰是国内的软肋。知已知彼,百战不殆。看到有什么不足,才能更好的补齐它。共同努力!

fpcc的专栏 8001

GB/T 27930-2023协议升级与CANoe仿真测试实践

本文深入解析GB/T 27930-2023协议的核心升级,包括A/B类系统分类与EVIN码引入,并详细指导如何使用CANoe搭建仿真测试环境、编写CAPL脚本及利用DLL库进行一致性验证与故障注入测试,助力开发人员确保电动汽车充电通信的合规性与稳定性。

y7z8a的博客 536

Win10 LTSC 2021 CPU占用率飙升?KB5017308补丁修复全攻略

本文针对Windows 10 LTSC 2021系统中因wsappx进程导致的CPU占用率异常飙升问题,提供了详细的解决方案。核心在于安装微软官方发布的KB5017308补丁,该补丁能从根本上修复系统组件缺陷,使CPU占用恢复正常。文章详解了补丁的下载、安装步骤、注意事项及安装后的验证方法,是解决此问题的权威指南。

python9snake的博客 1257

跟我学c++高级篇——反射的基本实现方式

太极生两仪,两仪有四象,四象生八卦。正如道家所说一生二,二生三,三生万物。学习也要从简单抓起,然后反复不停的在此基础上锤练,不断的向上发展,让整个体系愈发的完整并且向着新的未知不断的探索。对个人来说,技术的精湛莫不如是。对技术本身来说,更是如此。要站在巨人的肩膀上,不断的向前看,看向更高。

fpcc的专栏 7076

开关电源设计实战:如何用AP值快速选型磁芯(附计算公式推导)

本文为开关电源工程师提供了基于AP值的磁芯快速选型实战指南。文章深入解析了AP值作为磁芯‘功率吞吐量’指标的核心物理意义,并通过详细的公式推导和24W反激电源设计实例,手把手演示如何利用AP值计算公式,结合电流密度、窗口利用率等关键参数,从众多磁芯型号中高效筛选出合适型号,同时强调了选型后的关键校验步骤与常见误区。

weixin_29234239的博客 871

跟我学c++高级篇——C++26反射预览

看了c++26中的提案,可以发现其实很多现在的反射框架的轮子基本都可以废弃了。不过,能把反射最终支持,估计得2028年左右了,时间还有的是。喜欢造轮子的同学可以继续造,反正在造轮子的过程中,可以更好的学习反射的原理和实践,同样能更好的理解新标准中的反射。这样,在未来的应用中,也会更加轻松的引入标准库内的反射。在后面反射实现分析讲解中,基本也会沿着大致相同的路线进行。

fpcc的专栏 4057

cartographer如何使用2个反光柱子作为一个landmark

2个反光柱的摆放要求:靠着墙摆,因为我们只能从一侧看到2个反光柱,从两侧都看到至少需要3个反光柱来定位。 landmark检测原理:因为我们是从一侧看到2个反光柱,所以看到2个反光柱在一帧激光数据中会有顺序,有2种情形,如下图 这两种情形,我们发现 情形1: 这种情形2个反光柱子被检测到的激光角度小于180,我们认为大一些激光角度的是原点。 情形2: 这种情形2个反光柱子被检测到的激光角度大于180,我们认为小一些激光角度的是原点。 这样原点就固定下来,并是唯一的。2个反光柱构成的坐标系也就确定了。和激光坐

南北粉面馆 3827

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

跟我学c++高级篇——类反射

反射对c++是不是一种鸡肋,这个还真不好说。不过有一句话可以引入进来,“发展是硬道理”,只要是不断的发展,就会有机会。而停滞不前的空谈理论,一定是没有前途的。至于以后反射在c++后续标准里会成为什么样子,大家拭目以待即可。

fpcc的专栏 1580

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

跟我学c++高级篇——反射的基本原理

对反射在c++中的应用,大多数开发者可以忽略它。对国内来说更是如此,有兴趣可以搞一搞,如果没有兴趣的话,大可以束之高阁,等有需要的时候儿再拿起来现炒现卖,单纯在上层应用,肯定不会有多复杂。不用在过于担心会不会被标准扔得远远的。

fpcc的专栏 2742

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

跟我学c++高级篇——基础类型和POD结构体反射

由简入繁,从基本到深入总是需要一个过程,学习反射也是如此。写代码是为了把学习的知识验证一下,同时可以更加深刻的理解知识。开发者们经常遇到这种场景,几行简单的代码,琢磨半天也确定不了什么意思,但是上机一调试,就恍然大悟。这就是侯捷教师的那句话“源码之前,了无秘密”。反射还是有些难度的,所以这个系列会慢慢增加。

fpcc的专栏 1532

跟我学c++高级篇——静态反射实现之一

反射写起来非常头痛,一个是不知道如何说起更有系统性;另外一个就是哪种反射更有利于实际的应用。所以反射这个系列可能会是一个很长期的总结过程,大家不要着急,一定会把坑慢慢填好。

fpcc的专栏 1832

跟我学c++高级篇——reflexpr

这一章的实践意义并不大,但实际意义其实是很大的。学习知识最容易的方式不是直接拿过来用,也不是从头一点点的扣出来。学习知识最快捷的方式是把当下的技术搞明白,同时把某些关键技术的来历再理清晰,脉络分明后,学习的效率就会迅速增加。简单是技术普及的前提!

fpcc的专栏 956

跟我学C++高级篇——名称反射创建对象的一种实现

在后期的文章和实例中,大家会发现,会越来越多的把前面的知识融汇贯通,有可能再加上一些新知识点,就会实现一个比较好的技术点。所有的技术应用,一定是在基础技术上的不断的抽象升华。一种完全全新的,不以前边的技术为基础的技术,几乎很难遇到。或者如此说,即使遇到了,也可以通过老的技术快速的体会到新技术的优缺点。但这有一个前提,思想必须永远是开放包容,与时俱进!

fpcc的专栏 820

跟我学c++高级篇——静态反射实现之二函数接口实现

不断的抽象实现可以保证设计上的依赖于抽象而不依赖于实现,也就使得代码更有普适性。但多层次的抽象导致的结果可能是代码阅读上的困难和维护上不方便。这个就是仁者见仁了,一般来说,对于库等升级比较正式而且不怎么频繁的项目可以尽量抽象,而对于应用层,抽象要适当。不过在现在的环境下,就根据情况自己选择吧。

fpcc的专栏 644

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

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

fpcc的专栏 563

跟我学C++高级篇—运行时反射的std::type_index

C++通过std::type_index、type_info和typeid提供了轻量级的反射支持。typeid运算符返回type_info对象描述类型信息,type_index则是对其封装以便标准容器使用。主要应用场景包括类型映射、工厂模式、类型擦除等,但需注意哈希冲突、跨平台兼容性和异常处理等问题。示例展示了如何利用type_index构建类型管理系统。虽然C++的反射功能有限,但这些基础RTTI工具仍为开发者提供了类型操作的基本能力。随着标准演进,反射支持有望进一步完善。

fpcc的专栏 697

跟我学c++高级篇——动态反射之二动态列表

在上文说过,本来这篇是和上一篇打算合在一起,可是又觉得它们有点不同的意思,就拆分了开来。其实说来归去,重点是理解如何进行反射前的准备,把相关的字段名称都准备出来,只是同一个基础的应用,却可以在上层写出不同的反射方法来,这也是c++总被称为难的原因。因为其灵活,不容易掌握,而每个方法又有长处和不同的适应场景,这都需要开发者自己权衡,这就是难的原因。见仁见智,各取所需吧。

fpcc的专栏 418

跟我学c++高级篇——模板元编程之六SFINAE

SFINAE,对于想在模板编程中有更深的想法时,建议还是要认真学习。其实SFINAE更像是模板编程中更进阶的一种用法,虽然它可能在复杂的应用情况有些晦涩难懂,但既然决定想搞c++的模板编程,一些精深的东西还是需要去学习的。特别之于模板的元编程,更是如此。虽然有了concepts,但看以前的代码还是需要懂得这个技术的。

fpcc的专栏 4768
上一篇: 一步一步写线程之八线程池的完善之二数据结构封装
下一篇: DPDK系列之四十二DPDK应用网络编程UDP编程
fpcc
fpcc 新星创作者: C/C++技术领域 新星创作者: C/C++技术领域
博客等级 码龄22年 4038粉丝 1185原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值