• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            huaxiazhihuo

             

            完備的運行時類型信息

            眾所周知,碼猿寫代碼,自然要求嚴謹周密,殊不知想象力也很重要。本座閱碼幾十年,很是感概很多碼猿的腦洞被大大禁錮,鮮有人能越雷池一步,特別是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的;比如,以下的幾個判斷必須成立。
            TypeOf<int>() == TypeOf<int>();
            TypeOf<int>() == TypeOf(n);    //n為整型
            TypeOf<vector<int>>() == TypeOf(nums);//nums的類型為vector<int>
            Object* a = new ObjectA; TypeOf(a) == TypeOf<ObjectA>();
            其實這里面的原理也沒什么神奇,無非就是trait配合sfine,接下來就全部都是苦力活,就是為每一種類型都專門特化一個詳細描述的類型對象,用宏可以節省大量的代碼。但是整個反射庫,本座前前后后重構了十幾次,現在也還在重構之中,終究還是解決了開發上所遇到的各種事情。比如,序列化(支持指針、支持多態)、對象與xml的互換、對象與json的互換、數據庫表讀寫對象、格式化、Any類型、非侵入式接口、消息發送、字符串生成對象等等。
            其實現方式,概括起來,就是引入間接層元函數TypeInfoImp專門用于返回一個類型type,type里面有一個GetTypeInfo()的函數。然后TypeOf調用TypeInfoImp里的type的GetTypeInfo()最終得到TypeInfo對象。代碼如下所示。
                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;
                }
            可能可以有簡潔的方式,比如不需要引入TypeInfoImp,但是實際最終證明TypeInfoImp的方式最具靈活性也最能節省代碼。最起碼,它在自定義的struct或者class就很方便,只要改struct內部包含一個GetTypeInfo()的函數,它就可以被納入TypeOf體系中,非常方便。對于模板類型的TypeInfoImp,就要用到哈希表了。比如,對于std::paira的類型信息,如下實現,
                template<typename FstTy, typename SndTy>
                struct TypeInfoImp < std::pair<FstTy, SndTy> >
                {
                    static const bool value = true;
                    typedef TypeInfoImp < std::pair<FstTy, SndTy> > type;
                    static TypeInfo* GetTypeInfo()
                    {
                        ParamsTypeInfo<FstTy, SndTy> args;
                        return PodPair::LookupTemplateTypeInfo(args);
                    }
                };
            提取其類型參數的const TypeInfo*,生成數組。用此數組到PodPair的哈希表里面查找,如果哈希表中以有此類型數組參數的對象就返回,否則見創建一個添加一條哈希條目,然后返回。每一個泛型類型,比如vector,list,pair都有一個屬于自己的哈希表。
            打完收工。原理很簡單,但是對于工業級的反射庫,要考慮很多細節,比如,TypeInfo對象的內存管理;怎么為enum類型生成一堆字符串,以支持字符串和enume值的互相轉換;生成并保存class的構造函數和析構函數指針;命名空間的支持;仿真C#里面的attribute;如何以最方便的方式生成成員字段或者成員函數信息等等,一句話,就是他媽的體力活。但是,回報是很豐盛的,這里的苦力活做完之后,程序的其他地方上,基本上,就沒有什么重復相似的代碼,一切的體力工作全部就可以壓在類型信息這里了。

            posted on 2017-07-05 11:45 華夏之火 閱讀(1237) 評論(1)  編輯 收藏 引用 所屬分類: C++代碼自動生成

            評論

            # re: 完備的運行時類型信息 2017-07-06 10:47 天下

            老兄,看你的博文挺有意思的啊,繼續多寫點啊!
              回復  更多評論   

            導航

            統計

            常用鏈接

            留言簿(6)

            隨筆分類

            隨筆檔案

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            評論排行榜

            久久综合鬼色88久久精品综合自在自线噜噜| 欧美国产成人久久精品| 久久91综合国产91久久精品| 久久亚洲私人国产精品| 精品久久久久久综合日本| 久久国产精品免费一区| 大香伊人久久精品一区二区| 国内精品久久久久久久97牛牛| 久久精品国产只有精品2020| 久久综合伊人77777麻豆| 久久久久久久久久久久中文字幕| 久久综合欧美成人| 狠狠色狠狠色综合久久| 72种姿势欧美久久久久大黄蕉| 人妻无码久久精品| 色综合合久久天天综合绕视看| 久久精品成人欧美大片| 狠狠久久综合伊人不卡| AAA级久久久精品无码片| 97久久国产综合精品女不卡| 久久久久综合中文字幕| 伊人色综合久久天天| 99国产欧美久久久精品蜜芽| 亚洲国产精品成人久久| 免费精品久久久久久中文字幕 | 波多野结衣久久一区二区| 香港aa三级久久三级| 欧美一区二区三区久久综| 午夜精品久久影院蜜桃| 久久精品无码免费不卡| 99热成人精品免费久久| 91精品国产91久久| 99久久精品国内| 久久亚洲国产午夜精品理论片| 久久久久无码精品国产不卡| 综合久久国产九一剧情麻豆| 无码久久精品国产亚洲Av影片| 久久精品国产亚洲AV忘忧草18| 亚洲综合久久夜AV | 欧美无乱码久久久免费午夜一区二区三区中文字幕 | 久久99精品国产麻豆不卡|