一、反射框架介绍
在前面基本已经把基础的反射分析了一遍,通过这些学习,已经可以知道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++的技术知识融合起来。“一招鲜,吃遍天”,其实就是这个道理。要想“鲜”,就得把基础打好。有了基础,才是有源之水,才有可能把它们整合起来,才可能“一招鲜”。