• <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>

            qiezi的學習園地

            AS/C/C++/D/Java/JS/Python/Ruby

              C++博客 :: 首頁 :: 新隨筆 ::  ::  :: 管理 ::

            說明:
            要看懂后面那部分代碼,即使用Typelist的部分,最好預先看過《C++設計新思維》,英文版名為《Modern C++ Design》。
            If模板類在寫完后想起來好像在哪見過,早晨去公司查閱了一下,在《產生式編程——方法、工具與應用》一書中有講,英文名為《Generative Programming -- Methods, Tools, and Applications》基本和本篇中一個樣。


            前2篇亂七八糟地講了一些,有一個遺留問題,函數原型的推導。

            簡要描述如下:

            Method < void(in<int>in<char>, inout<string>out<short>> method;

            // 同步調用
            string str = "hello";
            short value = 2;
            method (
            3'a', str, value);

            // 異步調用1
            method.async_call (3'a'"hello");

            // 異步調用2
            void test_func (intcharstringshort);
            method.async_call (
            3'a'"hello", test_func);


            要產生這3種函數形式。參數類型如何轉換,是以后的話題,本篇主要解決異步調用的函數原形推導問題。本篇也不討論Method的模板參數(即那個函數類型)返回類型不為void的情況。

            第一種形式,同步調用,比較好處理,參數個數和模板參數的數量相同。

            后2種形式,如何讓編譯器根據in/out來推導出函數原型?

            我們需要編譯器做這樣的處理,async_call的參數類型中,in類型的參數將保留,out類型的參數不需要,inout類型也需要保留。

            要用到的Loki頭文件:

            #include <static_check.h>
            #include 
            <Typelist.h>

            using namespace Loki;
            using namespace Loki::TL;


            首先看看in/inout/out的聲明。為了簡化,這里去掉了跟類型推導無關的部分。

            class NullType
            {
                NullType ();
            };

            template 
            <class T>
            struct in
            {
                typedef T OriginalType;
            };

            template 
            <class T>
            struct out
            {
                typedef T OriginalType;
            };

            template 
            <class T>
            struct inout
            {
                typedef T OriginalType;
            };

            下面Method模板類的聲明,使用偏特化來產生代碼。為了簡化,我只取函數參數個數為4個參數的版本,比照著上面的代碼來解釋,只解釋method.async_call (3, 'a', "hello", test_func);這個版本,因為另一個比它簡單。

            template <class T>
            struct Method
            {
            };

            template 
            <class Ret, class A, class B, class C, class D>
            struct Method <Ret(A,B,C,D)> 
            {
            };


            根據上面Method的定義,Method < void(in, in, inout, out) > ,async_call函數的類型將是:

            typedef void (*FUNC_TYPE)(intcharstringshort);
            void async_call (intcharstring, FUNC_TYPE func);

            實際上FUNC_TYPE應該能夠接受更廣泛的類型,比如void(int, char, char*, short),這可以在內部做一些轉換,不過本篇的重點不在這里,所以只講上面的那種形式。

            直接在Method類中實現有些麻煩,所以我把這個函數放在一個基類中實現,只要編譯器能幫我們推導出下面這種形式就行了:

            template <class Ret, class A, class B, class C, class D>
            struct Method <Ret(A,B,C,D)> : public Base < A, B, C >
            {
            };


            注意,這里是以Method < void(in, in, inout, out) >這種形式來講的,才會有上面那種繼承關系。而實際上,由于in/out在參數中的位置、數量都是未知的,要到定義時才能確定,所以使用模板來推導。(入正題了)

            也就是說,只要我們能使用靜態推導方式,獲得A,B,C,D這四個參數中所有的in類型,把它交給Base作為模板參數就成了。

            這里需要一個輔助的模板類,用來在編譯時幫助推導:

            template <class T>
            class InOutTypeTraits
            {
                Loki::CompileTimeError 
            <false> Not_Supported_Type;
            };

            template 
            <class T>
            struct InOutTypeTraits < in<T> >
            {
                
            enum {isin=1, isout=0};
            };

            template 
            <class T>
            struct InOutTypeTraits < out<T> >
            {
                
            enum {isin=0, isout=1};
            };

            template 
            <class T>
            struct InOutTypeTraits < inout<T> >
            {
                
            enum {isin=1, isout=1};
            };

            template 
            <>
            struct InOutTypeTraits < NullType >
            {
                
            enum {isin=0, isout=0};
            };

            通過另一個模板類InList來幫我們產生所有的in類型,它的結果是一個Typelist。為了方便以后使用,我把out類型產生器也做了一個OutList。

            template <int CONDITION, class _IF, class _ELSE>
            struct If
            {
                typedef _IF Result;
            };

            template 
            <class _IF, class _ELSE>
            struct If <0, _IF, _ELSE>
            {
                typedef _ELSE Result;
            };

            template 
            <class A = NullType, class B = NullType, class C = NullType, class D = NullType, 
                
            class E = NullType, class F = NullType, class G = NullType, class H = NullType
            >
            struct InList
            {
                typedef typename If 
            < 
                    InOutTypeTraits 
            <A>::isin,
                    typename Typelist 
            < A, typename InList<B,C,D,E,F,G>::Result >
                    typename InList
            <B,C,D,E,F,G,H>::Result 
                
            >::Result Result;
            };

            template 
            <class A>
            struct InList <A, NullType, NullType, NullType, NullType, NullType, NullType, NullType>
            {
                typedef typename If 
            <
                    InOutTypeTraits 
            <A>::isin,
                    typename MakeTypelist 
            <A>::Result,
                    typename MakeTypelist 
            <>::Result
                
            >::Result Result;
            };

            template 
            <class A = NullType, class B = NullType, class C = NullType, class D = NullType, 
                
            class E = NullType, class F = NullType, class G = NullType, class H = NullType
            >
            struct OutList
            {
                typedef typename If 
            < 
                    InOutTypeTraits
            <A>::isout,
                    typename Typelist 
            < A, typename OutList<B,C,D,E,F,G>::Result >
                    typename OutList
            <B,C,D,E,F,G,H>::Result 
                
            >::Result Result;
            };

            template 
            <class A>
            struct OutList <A, NullType, NullType, NullType, NullType, NullType, NullType, NullType>
            {
                typedef typename MakeTypelist 
            <A>::Result Result;
            };

            它的原理是,根據If模板類來判斷一個類型是不是in類型,是的話就把它加入到Typelist中,不是就排除它。

            InList , in, inout, out::Result是一個Typelist , Typelist, Typelist, NullType> > >類型,說簡單點,它和MakeTypelist < in, in, inout >::Result是等價的。

            現在Base模板類將接受一個模板參數,它是一個Typelist類型,這個不詳細講了,把它的定義寫出來:

            template <class T, int T_COUNT = Length <IN_TYPE>::value >
            struct Base
            {
                Loki::CompileTimeError 
            <false> Only_Use_Partial_Specialisation_Version;
            };

            template 
            <class T>
            struct Base <T, 0>
            {
                typedef 
            void(*FUNC_TYPE)();

                template 
            <class FUNC_TYPE>
                
            void async_call (FUNC_TYPE func)
                {
                }
                
            void async_call ()
                {
                }
            };

            template 
            <class T>
            struct Base <T, 1>
            {
                typedef 
            void(*FUNC_TYPE)(
                    typename TypeAt 
            <T, 0>::Result::OriginalType);

                
            void async_call (
                    typename TypeAt 
            <T, 0>::Result::OriginalType v0,
                    FUNC_TYPE func)
                {
                }
                
            void async_call (typename TypeAt <T, 0>::Result::OriginalType v0)
                {
                }
            };

            template 
            <class T>
            struct Base <T, 2>
            {
                typedef 
            void(*FUNC_TYPE)(
                    typename TypeAt 
            <T, 0>::Result::OriginalType,
                    typename TypeAt 
            <T, 1>::Result::OriginalType);

                
            void async_call (
                    typename TypeAt 
            <T, 0>::Result::OriginalType v0, 
                    typename TypeAt 
            <T, 1>::Result::OriginalType v1, 
                    FUNC_TYPE func)
                {
                }
                
            void async_call (
                    typename TypeAt 
            <T, 0>::Result::OriginalType v0, 
                    typename TypeAt 
            <T, 1>::Result::OriginalType v1)
                {
                }
            };

            template 
            <class T>
            struct Base <T, 3>
            {
                typedef 
            void(*FUNC_TYPE)(
                    typename TypeAt 
            <T, 0>::Result::OriginalType, 
                    typename TypeAt 
            <T, 1>::Result::OriginalType,
                    typename TypeAt 
            <T, 2>::Result::OriginalType);

                
            void async_call (
                    typename TypeAt 
            <T, 0>::Result::OriginalType v0, 
                    typename TypeAt 
            <T, 1>::Result::OriginalType v1, 
                    typename TypeAt 
            <T, 2>::Result::OriginalType v2, 
                    FUNC_TYPE func)
                {
                }
                
            void async_call (
                    typename TypeAt 
            <T, 0>::Result::OriginalType v0,
                    typename TypeAt 
            <T, 1>::Result::OriginalType v1,
                    typename TypeAt 
            <T, 2>::Result::OriginalType v2)
                {
                }
            };

            template 
            <class T>
            struct Base <T, 4>
            {
                typedef 
            void(*FUNC_TYPE)(
                    typename TypeAt 
            <T, 0>::Result::OriginalType, 
                    typename TypeAt 
            <T, 1>::Result::OriginalType,
                    typename TypeAt 
            <T, 2>::Result::OriginalType,
                    typename TypeAt 
            <T, 3>::Result::OriginalType);

                
            void async_call (
                    typename TypeAt 
            <T, 0>::Result::OriginalType v0, 
                    typename TypeAt 
            <T, 1>::Result::OriginalType v1, 
                    typename TypeAt 
            <T, 2>::Result::OriginalType v2, 
                    typename TypeAt 
            <T, 3>::Result::OriginalType v3,
                    FUNC_TYPE func)
                {
                }
                
            void async_call (
                    typename TypeAt 
            <T, 0>::Result::OriginalType v0,
                    typename TypeAt 
            <T, 1>::Result::OriginalType v1,
                    typename TypeAt 
            <T, 2>::Result::OriginalType v2,
                    typename TypeAt 
            <T, 3>::Result::OriginalType v3)
                {
                }
            };

            這部分有點多,其實還是比較清晰的。注意這個Base的版本已經不是上面所講的那個了。

            函數原形推導問題就講完了。上面的代碼不一定還能編譯,昨天是能編譯的,被我修改了一些,為了解釋,又改成昨天那樣子。
            国产高潮国产高潮久久久| 久久人人爽人人爽人人片AV麻烦 | 久久99精品国产麻豆宅宅| 伊人久久大香线蕉av一区| 成人综合伊人五月婷久久| 情人伊人久久综合亚洲| 亚洲国产成人久久一区WWW| 一本一本久久A久久综合精品 | 91精品国产综合久久香蕉| 久久久久久久久久免免费精品| 亚洲精品蜜桃久久久久久| 久久国产香蕉视频| 99久久国语露脸精品国产| 无码任你躁久久久久久老妇| 久久婷婷五月综合97色一本一本 | 99久久精品国内| 一本一道久久a久久精品综合| 久久免费视频观看| 久久AV无码精品人妻糸列| 久久国产成人午夜aⅴ影院| 欧洲成人午夜精品无码区久久| 久久人人爽人人爽AV片| 久久中文字幕一区二区| 色偷偷久久一区二区三区| 久久久久青草线蕉综合超碰| 久久综合视频网站| 久久久国产精华液| 久久e热在这里只有国产中文精品99 | 久久99精品久久久久久噜噜 | 亚洲国产一成人久久精品| 亚洲欧美一级久久精品| 国产成人久久777777| 亚洲成色999久久网站| 麻豆精品久久精品色综合| 久久精品免费观看| 久久综合狠狠综合久久激情 | 色成年激情久久综合| 国产精品久久久久久久久鸭| 久久超乳爆乳中文字幕| 久久精品免费观看| 久久久这里有精品中文字幕|