晚上好!
继续更新第二篇,本文将介绍一些T0和T1阶段的C++反射库,对比探索其差异。
动态反射静态反射动态反射,就是类型元信息在运行期产生的反射,而静态反射则是在编译期产生。
诸多反射库,都借助了各种办法在运行期或是编译期来保存类型的信息,从而实现反射的能力。
这些实现又有「侵入式」和「非侵入式」之分。
侵入式会在你的类中添加一些保存类型信息的组件,这往往会采用宏来自动产生,隐藏实现细节。
这种方式可以得到类型中的私有信息,因为往往会把保存信息的组件置为友元。但毫无疑问,此法会破坏原有类型的结构,一般这种库没人会用。
非侵入式则是在类外声明一些组件来收集类型元信息,这也是大多数反射库采取的实现方式。
同样,具体实现也会被隐藏起来,使用宏来自动产生相关代码,主要原因是为了使用方便。然而,此法无法得到类型中的私有信息,这是一处限制。另外,有些库利用一些技巧,从而无需手动注册类型信息,不过限制亦多。
总的来说,不可避免地,大多数库都需要用户手动地填写类型信息,这是反射机制缺少所致,因此使用起来多少都会有些限制。
以下各节,分别来介绍一些C++的反射库,探索一下基本用法。
BoostDescribeLibrary第一,来看Boost中包含的一个C++14反射库:Describe。
该库支持枚举、结构体和类的反射,先来看个官方提供的小例子:
#includeiostream#includeboost/describe.hpp#includeboost/mp11.hppenumE{v1=1,v2=2,v3=3};BOOST_DESCRIBE_ENUM(E,v1,v2,v3)intmain(){usingL1=boost::describe::describe_enumeratorsE;boost::mp11::mp_for_eachL1([](autoD){std::coutD.name":"static_castint(D.value)std::endl;});return0;}
这个例子同样是用于输出枚举类型的值。
那么它是从哪得到枚举类型信息的呢?注意这里的BOOST_DESCRIBE_ENUM宏,此宏便是用来自动产生收集「枚举类型的元信息」的代码。
这个宏支持可变参数,第一个参数就是枚举类型,其后的参数则是枚举中的字段。
通过这种手动注册的方式,该库就可以提供类型的元信息。
对于以上例子,这个宏将自动展开成如下代码:
static_assert(std::is_enumE::value,"BOOST_DESCRIBE_ENUMshouldonlybeusedwithenums");inlineautoboost_enum_descriptor_fn(E*){returnboost::describe::detail::enum_descriptor_fn_impl(0,[]{struct_boost_desc{staticconstexprautovalue()noexcept{returnE::v1;}staticconstexprautoname()noexcept{return"v1";}};return_boost_desc();}(),[]{struct_boost_desc{staticconstexprautovalue()noexcept{returnE::v2;}staticconstexprautoname()noexcept{return"v2";}};return_boost_desc();}(),[]{struct_boost_desc{staticconstexprautovalue()noexcept{returnE::v3;}staticconstexprautoname()noexcept{return"v3";}};return_boost_desc();}());}
可以看到,这里自动产生了一系列代码来保存枚举类型的信息。
根据自动产生的这个boost_enum_descriptor_fn函数,它就能构建类型的描述信息,
templateclassEusingdescribe_enumerators=decltype(boost_enum_descriptor_fn(static_castE*(0)));
也因如此,主函数中的describe_enumerators才有了定义:
usingL1=boost::describe::describe_enumeratorsE;boost::mp11::mp_for_eachL1([](autoD){std::coutD.name":"static_castint(D.value)std::endl;});
然后,通过mp11的mp_for_each便可以迭代类型的所有信息。
该库使用起来还算方便,但是也有一些限制,后面再来看。
RTTRLibrary第二,来看一个使用人数较多的C++动态反射库:rttr。
该库的文档比较充足,有专门的网站