一种更通用的编译期反射
来源:互联网 发布:防止微信屏蔽分享域名 编辑:程序博客网 时间:2024/05/01 02:26
magic_get编译期反射的局限性
magic_get可以实现编译期获取pod类型,是以一种“无痕”的方式实现的,即无需宏、特殊标记、专门工具。看起来确实很精妙,不过也存在一些局限性,比如只能支持pod类型,不能获取反射类型的字段名,也不支持遍历访问对象字段。这些局限性导致magic_get无法在更广泛的环境下应用。
一种更通用的编译期反射方法
基本的反射功能应该包括根据索引获取字段,根据索引获取字段名,遍历对象的所有字段,支持所有类型的对象。
一种更通用的编译期反射应该支持下面这些。
struct city_t{ int id; double num;};REFLECTION(city_t, id,num);struct person_t{ int id; double num; city_t city;};REFLECTION(person_t, id,num,city);int main(){ city_t city = {20, 3.5}; person_t p = {1,2.5,city}; //get filed name by index constexpr auto filed_name = get_name<person_t, 1>(); //get value by index auto val = get<1>(p); //apply algorithm to every member of struct for_each(p, [](auto& v, size_t I) { v*=10; std::cout<< v <<std::endl; }); }
这种编译期反射有几个优点:使用简单,通用,接口完备,支持所有类型的对象而不仅仅是pod类型,非侵入式。
存在的不足之处在于需要定义一个宏,这个非侵入式的宏是用来获取对象的元数据的,是不可少的。magic_get之所以不需要定义宏,是因为利用了pod类型内存连续的特殊性,可以直接转换为内存连续的tuple。虽然这个tuple提供了元数据,但是这个元数据是有缺陷的,即只有字段值而没有其他信息。而定义宏的方式则提供了丰富而完整的元数据信息,会更通用和方便。
由于这种编译期反射方式把对象元数据和元数据的操作分离了,所以用户可以基于这个通用的编译期反射做自己感兴趣的事情。
编译期反射可以用来做什么
编译期反射非常适合用来做ORM引擎和序列化/反序列化引擎,以ORM为例,我们可以基于反射来做多种数据库的ORM,比如sqlite, mysql, postgresql,oracle,sqlserver等数据库。有了ORM之后使用起来会非常方便,给用户提供简单通用的接口,把数据库差异、对象和实体相互转换等繁琐的细节都屏蔽了。以基于编译期反射实现sqlite的ORM为例:
struct person{ int id; char* name; int age; blob address;};REFLECTION(person, id,name,age,address);int main(){ dbng db; //sqlite数据库对象 int result = db.create_database("test.db"); const char* create_tb = "create table if not exists person(id integer, name text, age integer, address blob);"; result = db.exceute(create_tb); //插入数据,参数平铺方式 const char* insert_person = "insert into person(id,name,age,address) values(?,?,?,?);"; db.excecute(insert_person, 2, "jim", 30, blob{"zhuhai", 6}); //插入数据,对象方式,通过编译期反射实现对象到实体的映射 person p = {3, "mike", 40, blob{"zhuhai", 6}}; db.excecute(insert_person, p); //数据查询,通过编译期反射实现实体到对象的映射 const char* query_all = "select * from person"; db.query<person>(query_all); //查询部分数据,由于查询的字段是任意组合,所以需要使用tuple来作为任意实体到对象的映射 const char* query_some = "select name, age from person"; db.query<std::tuple<char*, int>>(query_some);}
从上面的例子可以看到,基于编译期反射实现的ORM接口非常简单、通用和强大,你几乎可以用这几个接口做任何事。即使对于其他数据库,接口仍然保持不变,这将会极大地提高数据库开发效率和降低数据库开发的难度,这就是编译期反射的威力!
关于编译期反射的实现原理和ORM的实现原理敬请关注即将开始的purecpp社区第一期技术公开课!
- 一种更通用的编译期反射
- 在Linux下更通用的一种软件安装方式
- 基于反射List转Map的一种通用泛型实现
- 一种在编译期保证模板类参数T必须实现某函数的方法
- 一种通用的接口设计方案
- Makefile的一种通用写法
- java泛型检查只在编译期有效,而反射是在运行期的调用机制。
- java泛型检查只在编译期有效,而反射是在运行期的调用机制。
- 编译期的优化
- 反射的另外一种方法
- 让Scrapy的Spider更通用
- PostCSS一种更优雅、更简单的书写CSS方式
- 一种更清晰的Android架构
- 一种更清晰的Android架构
- 一种更清晰的Android架构
- 一种更清晰的Android架构
- 一种更清晰的Android架构
- 一种更清晰的Android架构
- ROLL A BALL 小游戏
- eclipse插件在真实环境中没有效果
- 数据库管理平台
- 学习记录——网络层(4)
- Effective java读书笔记
- 一种更通用的编译期反射
- 笔记,执行mybatis自动映射的语句
- 使用C#将HTML文本转换为普通文本,去掉所有的Html标记
- codevs 1638_洛谷 1111_修复公路_并查集
- 网站美化常见CSS
- delphi 用别名的方式访问excel写入数据,实现非标格式报表输出
- 浅谈CSS3新特性——动画animation
- 支付
- handler的使用