c++ 完备的运行时类型信息(动态类型信息)
副标题[/!--empirenews.page--]
众所周知,码猿写代码,自然要求严谨周密,殊不知想象力也很重要。本座阅码几十年,很是感概很多码猿的脑洞被大大禁锢,鲜有人能越雷池一步,特别是c++的同学,连同委员会的那一坨老头子,都很让人无语至极,出自这些人的作品,都是一个死鱼眼睛样子,千人一面,毫无灵动之生趣可言。stl,boost这些库都是这样子(虽然它们确实可以完成大多数日常任务),更别说其他的库,没有什么让人耳目一新之处。 就说说动态类型信息这块,又或者说是反射。自然,语言本身提供的废物type_info就懒得说了,除了证明c++也东施效颦,也能支持动态信息之外,就别无用处了,有谁会正儿八经的用type_info做点正儿八经的事情呢。因此,各路人马纷纷上阵,都要弥补c++在运行时类型信息上的缺失。因为类型的反射信息实在太重要,或者说,反射的用武之地太多太多,表面上很多事情不需要反射,或者字面代码上就看不到反射的痕迹,但是内里的实现,大把大把的反射在发光发热。c++坚持不在动态信息上给予一点点多余的支持,并不表示c++就不需要反射了,看看标准库这个极力回避动多态的典范,是一个怎样的失败作品,嗯,这个以后再谈吧。假如stl一开始就没有如此大力排斥动多态,你看看就连内存分配的allocator都可以做到静态类型信息里面(最新版的c++终于也要接受多态的allocator,c++界居然一片欢呼鼓舞,真是悲哀),今时今日的c++就不会在很多领域上到处割地求和。 总的来说,现在市面上的c++反射库,都是侵入式,都学着mfc那一套,都是要求继承自一个基类Object,然后才能对外提供反射信息的功能,先不说它们提供的类型信息是否完备,这样子就把用途广泛限制死在一个很窄很窄的小圈子里面了。这些反射库,1、不能反射基本类型,int、char、double、const char*、……等;2、不能反射非继承自Object的class或者struct,3、也不能反射模板类,比如vector<int>、list<vector<vector<int>>>。虽然typeid千般弱鸡,但也非一无是处,起码非侵入、平等、多态。所以,理想的反射,应该像c++原生的typeid那样无色无味:1、非侵入式的;2、可以对所有的类型都提供反射,基本类型、非Object系的struct或者class、template类型的;3、多态的,只要改类型需要运行时的类型识别,那么就返回其本身的类型(子类),而非字面上的声明类型;4、支持类型参数,也即是说,以类型传递给该函数时,就返回相应的类型信息对象。 说得具体一点,我们要求的反射库是这样子的。当然,首先要有一个类型信息对象TypeInfo,里面装满了关于对于类型的所有详细信息。如下所示:可以猜到这种反射下框架,只支持单继承,这是故意的。 struct TypeInfo { public: template<typename Args> void ConstructObject(void* obj,MemoryAllocator* alloc,Args&& args)const; bool IsDerviedOf(const TypeInfo* base)const; public: virtual TIType GetTIType()const = 0; virtual const InterfaceMap* GetInterfaces()const; virtual jushort GetMemorySize()const; virtual ConstText GetName() const; virtual AString GetFullName()const; virtual jushort GetAlignSize() const; virtual ConstText GetSpaceName()const; virtual const TypeInfo* GetBaseTypeTI()const; virtual const TypeInfo* GetPointeedTI()const; virtual size_t GetHashCode(const void* obj)const; virtual bool IsValueType()const { return true; } virtual bool IsClass()const { return true; } virtual bool DoInitAllocator(void* obj,MemoryAllocator* memAlloc)const; virtual bool NeedDestruct()const { return false; } virtual void DoDefaultConstruct(void* obj)const; virtual bool CanDefaultConstruct()const { return true; } virtual void DoAssign(void* dest,const void* src)const; virtual bool Equals(const void* objA,const void* objB)const; virtual void DoDestruct(void* obj)const; }; 然后,就要有一个函数TypeOf,应该是两个,一个是无参数的类型模板函数,可以这样调用,TypeOf<type>();一个是有一个参数的类型模板函数,可以这样调用,TypeOf(obj)。不管是那一个,其返回结果都是const TypeInfo*。TypeOf的要做到的事情是,对于每一种类型,有且只有一个唯一的TypeInfo对象与之对应,不管是template的还是非template的;比如,以下的几个判断必须成立。 template<typename Ty> struct TypeInfoImp { typedef Ty type; static const bool value = THasGetTypeInfoMethod<Ty>::value; }; template<typename Ty> struct TypeInfoImp<const Ty> : public TypeInfoImp<Ty> { typedef typename TypeInfoImp<Ty>::type type; static const bool value = TypeInfoImp<Ty>::value; }; template<typename Ty> const TypeInfo* TypeOf() { typedef typename TypeInfoImp<Ty>::type TypeInfoProvider; return TypeInfoProvider::GetTypeInfo(); } template<typename Ty> const TypeInfo* TypeOf(const Ty& obj) { typedef typename IsRttiType<Ty>::type is_rtti; //又是间接层,对动态类型和非动态类型分别处理 return ImpTypeOf(obj,is_rtti()); } template<> struct TypeInfoImp < bool > { static const bool value = true; typedef TypeInfoImp<bool> type; static TypeInfo* GetTypeInfo(); }; TypeInfo* TypeInfoImp<bool>::GetTypeInfo() { static TypeInfo* ti = CreateNativeTypeInfo<bool>("bool"); return ti; } (编辑:淮安站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |