• <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>
            隨筆 - 31  文章 - 128  trackbacks - 0
            <2006年7月>
            2526272829301
            2345678
            9101112131415
            16171819202122
            23242526272829
            303112345

            常用鏈接

            留言簿(5)

            隨筆分類(lèi)(38)

            隨筆檔案(31)

            收藏夾(4)

            College

            High School

            最新隨筆

            搜索

            •  

            積分與排名

            • 積分 - 55886
            • 排名 - 407

            最新評(píng)論

            • 1.?re: [yc]詳解link
            • 面試的時(shí)候面試官就問(wèn)過(guò)我什么是編譯和鏈接,我說(shuō)編譯就是把代碼文件生成目標(biāo)文件,鏈接就是把目標(biāo)文件生成可執(zhí)行文件,他說(shuō)不對(duì),又問(wèn)我什么是動(dòng)態(tài)鏈接,還問(wèn)我預(yù)編譯都做什么處理。。。都在這里找到了答案!!!!
            • --王至乾
            • 2.?re: [yc]詳解link
            • @劉偉
              我是說(shuō)博主,不是叫你啊
            • --溪流
            • 3.?re: [yc]詳解link
            • 誰(shuí)是石老師,我不是哈@溪流
            • --劉偉
            • 4.?re: [yc]詳解link
            • 石老師?我是溪流~
            • --溪流
            • 5.?re: [yc]詳解link
            • 期待樓主下文啊,多謝樓主了
            • --劉偉

            閱讀排行榜

            評(píng)論排行榜

            發(fā)信人: shifan (家沒(méi)有豚豚 T.T), 板面: C++
            標(biāo)  題: 如何實(shí)現(xiàn)Lambda[第二部分]
            發(fā)信站: 飄渺水云間 (Thu Jun  8 23:30:20 2006), 轉(zhuǎn)信


            章節(jié):
            八:第一部分的小結(jié)
            九:簡(jiǎn)化,如何減少Lambda代碼的冗余和依賴(lài)性
            十:bind的實(shí)現(xiàn)
            十一:實(shí)現(xiàn)phoenix


            八.    中期總結(jié)
            目前的結(jié)果是這樣的,為了支持一個(gè)操作符,我們需要作如下幾件事:
                1。 實(shí)現(xiàn)一個(gè)functor,該functor的operator()要能執(zhí)行該操作符的語(yǔ)義
                2。 在該functor中實(shí)現(xiàn)result_1至result_n,其中n是支持參數(shù)的最大值。
                3。 在picker中實(shí)現(xiàn)一個(gè)操作符重載,返回該functor

             


            九. 簡(jiǎn)化
            很明顯,要支持一個(gè)操作符所要做的工作太多了,而且在每個(gè)functor中申明result_1至
            result_n,可見(jiàn)如果n發(fā)生變化,維護(hù)的開(kāi)銷(xiāo)極大。
            我們現(xiàn)在需要找到一個(gè)自動(dòng)生成這種functor的方法。
            首先,我們注意到result_x的形式很統(tǒng)一。對(duì)于各種操作符,其返回值無(wú)非下列幾種:
                1.  返回值。如果本身為引用,就去掉引用。
                        +-*/&|^等
                2.  返回引用。
                        =,各種復(fù)合賦值等
                3.  返回固定類(lèi)型。
                        各種邏輯/比較操作符(返回bool)
                4.  原樣返回。
                        operator,
                5.  返回解引用的類(lèi)型。
                        operator*(單目)
                6.  返回地址。
                        operator&(單目)
                7.  下表訪問(wèn)返回類(lèi)型。
                        operator[]
                8.  如果左操作數(shù)是一個(gè)stream,返回引用,否則返回值
                        operator<<和operator>>

            OK,這樣我們將返回值類(lèi)型總結(jié)為以上8種,就可以將各種result_x從functor中剝離出來(lái)了

            例如針對(duì)第一條,我們實(shí)現(xiàn)一個(gè)policy類(lèi):
                

            template < typename Left >
                
            struct  value_return
                
            {
                    template
            < typename T >
                    
            struct  result_1
                    
            {
                        typedef typename const_value
            < typename Left::template
            result_1
            < T > ::result_type > ::value_type result_type;
                    }
            ;

                    template
            < typename T1, typename T2 >
                    
            struct  result_2
                    
            {
                        typedef typename const_value
            < typename Left::template result_2 < T1,
            T2
            > ::result_type > ::value_type result_type;
                    }
            ;
                }
            ;

            其中const_value是一個(gè)將一個(gè)類(lèi)型轉(zhuǎn)為其非引用形式的trait

            下面我們來(lái)剝離functor中的operator()
            首先operator里面的代碼全是下面的形式:
               

               return l(t) op r(t)
                
            return l(t1, t2) op r(t1, t2)
                
            return op l(t)
                
            return op l(t1, t2)
                
            return l(t) op
                
            return l(t1, t2) op
                
            return l(t)[r(t)]
                
            return l(t1, t2)[r(t1, t2)]


            很自然的,我們會(huì)想到用函數(shù)替代這種操作符行為以獲得更加一致的形式:
                單目:  return f(l(t), r(t));
                    return f(l(t1, t2), r(t1, t2));
                雙目:  return f(l(t));
                    return f(l(t1, t2));
            下面就是f的實(shí)現(xiàn),以operator/為例

                 struct  meta_divide
                
            {
                    template 
            < typename T1, typename T2 >
                    
            static  ret execute( const  T1 &  t1,  const  T2 &  t2)
                    
            {
                        
            return  t1  /  t2;
                    }

                }
            ;


            這個(gè)工作可以讓宏來(lái)做:

                 #define  DECLARE_META_BIN_FUNC(op, desc, ret) struct meta_##desc{\
                    template 
            < typename T1, typename T2 >  \
                    
            static  ret execute( const  T1 &  t1,  const  T2 &  t2)  { return  ((T1 & )t1) op
            ((T2
            & )t2);}
             };


            以后可以直接用
                DECLARE_META_BIN_FUNC(/, divide, T1)
            來(lái)申明meta_divide。同樣還可以申明宏DECLARE_META_UNY_PRE_FUNC和
            DECLARE_META_UNY_POST_FUNC來(lái)產(chǎn)生單目前綴和后綴操作符的函數(shù)
            (ps.我本堅(jiān)持該lambda實(shí)現(xiàn)不使用宏的,但是在這種小劑量的又很一致的代碼面前,使用
            宏實(shí)在是很誘人。。。)


            下面就是要把operator()和result_x拼湊起來(lái),形成一個(gè)我們要的functor,下面是一個(gè)單目
            的functor的實(shí)現(xiàn)體

                template < typename Left, typename Right, typename Rettype, typename FuncType >
                
            class  unary_op :  public  Rettype
                
            {
                        Left l;
                
            public :
                        unary_op(
            const  Left &  l) : l(l) {}

                    template
            < typename T >
                        typename Rettype::template result_1
            < T > ::result_type  operator ()( const
            T
            &  t)  const
                        
            {
                            
            return  FuncType::execute(l(t));
                        }


                        template
            < typename T1, typename T2 >
                        typename Rettype::template result_2
            < T1, T2 > ::result_type
            operator ()( const  T1 &  t1,  const  T2 &  t2)  const
                        
            {
                            
            return  FuncType::execute(l(t1, t2));
                        }

                }
            ;

            同樣還可以申明一個(gè)binary_op

                template < typename Left, typename Right, typename Rettype, typename FuncType >
                
            class  binary_op :  public  Rettype
                
            {
                        Left l;
                    Right r;
                
            public :
                        binary_op(
            const  Left &  l, const  Right &  r) : l(l), r(r) {}

                    template
            < typename T >
                        typename Rettype::template result_1
            < T > ::result_type  operator ()( const
            T
            &  t)  const
                        
            {
                            
            return  FuncType::execute(l(t), r(t));
                        }


                        template
            < typename T1, typename T2 >
                        typename Rettype::template result_2
            < T1, T2 > ::result_type
            operator ()( const  T1 &  t1,  const  T2 &  t2)  const
                        
            {
                            
            return  FuncType::execute(l(t1, t2), r(t1, t2));
                        }

                }
            ;

            很完美不是么,unary_op/binary_op繼承了Rettype, 也就擁有了該類(lèi)所定一個(gè)全部
            result_x, 同時(shí)使用FuncType來(lái)執(zhí)行運(yùn)算符操作,很漂亮
            比如要支持操作符operator+,則需要寫(xiě)一行
                DECLARE_META_BIN_FUNC(+, add, T1)
            那么binary_op<Left, Right, value_return, meta_add>就自然是operator+(雙目)的
            functor,不需要自己手動(dòng)實(shí)現(xiàn)。
            停!不要陶醉在這美妙的幻覺(jué)中!
            如果把這段代碼拿到VC7或VC8下編譯,你會(huì)得到很有趣的結(jié)果。。。
            好了,這不是我們的錯(cuò),但是確實(shí)我們應(yīng)該解決它。
            這實(shí)際上是vc的bug,解決方法是不要去使用typename Rettype::template result_2<T1,
            T2>::result_type這樣的形式。(感謝vbvan)
            下面是修改過(guò)的unary_op

                template < typename Left, typename OpClass, typename RetType >
                
            class  unary_op
                
            {
                    Left l;

                
            public :

                    unary_op(
            const  Left &  l) : l(l) {}

                    template
            < typename T >
                    
            struct  result_1
                    
            {
                        typedef typename RetType::template result_1
            < T > ::result_type
            result_type;
                    }
            ;

                    template
            < typename T1, typename T2 >
                    
            struct  result_2
                    
            {
                        typedef typename RetType::template result_2
            < T1, T2 > ::result_type
            result_type;
                    }
            ;

                    template
            < typename T1, typename T2 >
                    typename result_2
            < T1, T2 > ::result_type  operator ()( const  T1 &  t1,  const
            T2
            &  t2)  const
                    
            {
                        
            return  OpClass::execute(lt(t1, t2));
                    }


                    template
            < typename T >
                    typename result_1
            < T > ::result_type  operator ()( const  T &  t)  const
                    
            {
                        
            return  OpClass::execute(lt(t));
                    }


                }
            ;

            該方法避免直接使用RetType的result_x,而自己申明一個(gè)對(duì)應(yīng)的result_x做一次中轉(zhuǎn),雖
            然其實(shí)毫無(wú)意義,卻恰好避開(kāi)了vc的bug
            好啦,現(xiàn)在才真正完美了。
            現(xiàn)在在picker里面就可以這么添加了:

                template < typename Right >
                picker
            < binary_op < Action, typename picker_maker < Right > ::result_type,
            ref_return
            < Action > , meta_add_assign >   >   operator += ( const  Right &  rt)  const
                
            {
                    
            return  binary_op < Action, typename picker_maker < Right > ::result_type,
            ref_return
            < Action > , meta_add_assign > ( * this , rt);
                }

            有點(diǎn)長(zhǎng)不是么?不過(guò)實(shí)際代碼量減少了很多,而且此后如果支持的參數(shù)上限發(fā)生變化,我們
            就只需要修改binary_op和unary_op就行了。

             


            十.    bind
            既然都做到這份上了,我們順便把bind也做了吧,其實(shí)事情已經(jīng)變得很簡(jiǎn)單了。
            先來(lái)分析一下一段例子

            int  foo( int  x,  int  y) { return  x  -  y;}
            bind(foo, _1, constant(
            2 )( 1 )   // return -1
            bind(foo, _2, _1)( 3 6 )   // return foo(6, 3) == 3

             

            可見(jiàn)bind是一系列重載函數(shù),返回某種functor,該functor的執(zhí)行就是執(zhí)行傳進(jìn)bind的函數(shù)
            指針并正確的確定參數(shù)。
            我們來(lái)寫(xiě)個(gè)簡(jiǎn)單的。
            首先要知道一個(gè)函數(shù)的返回類(lèi)型,我們使用一個(gè)trait來(lái)實(shí)現(xiàn):
            對(duì)于函數(shù)對(duì)象類(lèi)的版本:

                template < typename Func >
                
            struct  functor_trait
                
            {
                    typedef typename Func::result_type result_type;
                }
            ;


            對(duì)于無(wú)參數(shù)函數(shù)的版本:

                template < typename Ret >
                
            struct  functor_trait < Ret ( * )() >
                
            {
                    typedef Ret result_type;
                }
            ;


            對(duì)于單參數(shù)函數(shù)的版本:

                template < typename Ret, typename V1 >
                
            struct  functor_trait < Ret ( * )(V1) >
                
            {
                    typedef Ret result_type;
                }
            ;


            對(duì)于雙參數(shù)函數(shù)的版本:

                template < typename Ret, typename V1, typename V2 >
                
            struct  functor_trait < Ret ( * )(V1, V2) >
                
            {
                    typedef Ret result_type;
                }
            ;


            等等。。。
            然后我們就可以仿照value_return寫(xiě)一個(gè)policy

                template < typename Func >
                
            struct  func_return
                
            {
                    template
            < typename T >
                    
            struct  result_1
                    
            {
                        typedef typename functor_trait
            < Func > ::result_type result_type;
                    }
            ;

                    template
            < typename T1, typename T2 >
                    
            struct  result_2
                    
            {
                        typedef typename functor_trait
            < Func > ::result_type result_type;
                    }
            ;
                }
            ;

            最后一個(gè)單參數(shù)binder就很容易寫(xiě)出來(lái)了

                template < typename Func, typename aPicker >
                
            class  binder_1
                
            {
                    Func fn;
                    aPicker pk;
                
            public :

                    template
            < typename T >
                    
            struct  result_1
                    
            {
                        typedef typename func_return
            < Func > ::template
            result_1
            < T > ::result_type result_type;
                    }
            ;

                    template
            < typename T1, typename T2 >
                    
            struct  result_2
                    
            {
                        typedef typename func_return
            < Func > ::template result_2 < T1,
            T2
            > ::result_type result_type;
                    }
            ;

                    binder_1(Func fn, 
            const  aPicker &  pk) : fn(fn), pk(pk) {}

                    template
            < typename T >
                    typename result_1
            < T > ::result_type  operator ()( const  T &  t)  const
                    
            {
                        
            return  fn(pk(t));
                    }

                    template
            < typename T1, typename T2 >
                    typename result_2
            < T1, T2 > ::result_type  operator ()( const  T1 &  t1,  const
            T2
            &  t2)  const
                    
            {
                        
            return  fn(pk(t1, t2));
                    }

                }
            ;

            一目了然不是么?
            最后實(shí)現(xiàn)bind

                template < typename Func, typename aPicker >
                picker
            < binder_1 < Func, aPicker >   >  bind( const  Func fn,  const  aPicker &  pk)
                
            {
                    
            return  binder_1 < Func, aPicker > (fn, pk);
                }


            2個(gè)以上參數(shù)的bind可以同理實(shí)現(xiàn)。
            另外還可以照樣實(shí)現(xiàn)一系列binder來(lái)綁定類(lèi)成員函數(shù)/變量,手法雷同,就不詳細(xì)介紹了。

             

             

             


            十一.    phoenix
            Boost.phoenix可能知道的人不多,讓我們來(lái)看一段代碼吧:

                for_each(v.begin(), v.end(),
                (
                    do_
                    [
                        cout 
            <<  _1  <<   " "
                    ]
                    .while_(
            -- _1),
                    cout 
            <<  var( " \n " )
                    )
                );


            是不是華麗的讓人撞墻?其實(shí)這個(gè)比想象的好實(shí)現(xiàn)的多。還是照慣例分析一下吧:
            首先do_很明顯是個(gè)對(duì)象,該對(duì)象重載了operator[],接受一個(gè)functor作為參數(shù),并返回另
            一個(gè)對(duì)象,該對(duì)象有一個(gè)成員函數(shù)while_,同樣接受一個(gè)functor作為參數(shù),并返回一個(gè)

            functor, 最后2個(gè)functor用operator, 生成一個(gè)新的functor
            operator,的實(shí)現(xiàn)這里略過(guò)了,請(qǐng)參照前面的描述。
            那么我們就照著這個(gè)思路來(lái)實(shí)現(xiàn)吧:

                template < typename Cond, typename Actor >
                
            class  do_while
                
            {
                    Cond cd;
                    Actor act;
                
            public :
                    template
            < typename T >
                    
            struct  result_1
                    
            {
                        typedef 
            int  result_type;
                    }
            ;

                    do_while(
            const  Cond &  cd,  const  Actor &  act) : cd(cd), act(act) {}

                    template
            < typename T >
                    typename result_1
            < T > ::result_type  operator ()( const  T &  t)  const
                    
            {
                        
            do
                        
            {
                            act(t);
                        }

                        
            while  (cd(t));
                        
            return   0 ;
                    }

                }
            ;

            這就是最終的functor,我略去了result_2和2個(gè)參數(shù)的operator().
            代碼很清晰,但是還是讓我來(lái)解釋一下為什么要用int作為返回類(lèi)型。
            其實(shí)對(duì)于do-while語(yǔ)義,返回類(lèi)型是無(wú)意義的,然而將其定義為void會(huì)影響在某些情況下
            return的簡(jiǎn)潔性,因?yàn)閞eturn一個(gè)void是不合法的。
            因此我們將其定為int,并返回0,這樣減少了其它地方編碼的復(fù)雜度。
            下面就是產(chǎn)生這個(gè)functor的類(lèi):

                template < typename Actor >
                
            class  do_while_actor
                
            {
                    Actor act;
                
            public :
                    do_while_actor(
            const  Actor &  act) : act(act) {}

                    template
            < typename Cond >
                    picker
            < do_while < Cond, Actor >   >  while_( const  Cond &  cd)  const ;
                }
            ;

            簡(jiǎn)單吧,注意到這個(gè)while_函數(shù),它自動(dòng)的生成了一個(gè)do_while對(duì)象。
            最后,是那個(gè)do_

                 class  do_while_invoker
                
            {
                
            public :
                    template
            < typename Actor >
                    do_while_actor
            < Actor >   operator [](Actor act)  const
                    
            {
                        
            return  do_while_actor < Actor > (act);
                    }

                }
            do_;


            好啦,現(xiàn)在明白do_[xxx].while_(xxx)是怎么工作的吧?
            同樣的,我們還可以做if_, while_, for_, switch_等。
            最后來(lái)說(shuō)說(shuō)怎么處理break和continue
            顯然break的語(yǔ)義超出了我們的能力范圍,然而卻是有一個(gè)東西很適合模擬其行為,那就是
            異常。
            具體實(shí)現(xiàn)手法這里就不羅嗦了。
            --
            You well 撒法!You well all 撒法!

            ※ 來(lái)源:·飄渺水云間 freecity.cn·[FROM: shifan]                                                                       

            posted on 2006-07-15 15:32 shifan3 閱讀(990) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): templateBoostC++
            久久天堂电影网| 一本色道久久88综合日韩精品 | 久久综合狠狠色综合伊人| 久久99国产精品久久| 亚洲国产精品成人AV无码久久综合影院| 久久亚洲私人国产精品| 久久综合九色综合97_久久久| 色妞色综合久久夜夜| 久久国产乱子伦精品免费午夜| 91精品国产91久久久久福利| 久久精品三级视频| 国产午夜精品理论片久久影视| 久久国产欧美日韩精品| 少妇被又大又粗又爽毛片久久黑人| 国产ww久久久久久久久久| 香蕉久久av一区二区三区| 无夜精品久久久久久| 91精品无码久久久久久五月天| 精品久久一区二区三区| 一本色道久久88综合日韩精品| 伊人久久大香线蕉成人| 国产伊人久久| 94久久国产乱子伦精品免费| 久久亚洲AV成人无码电影| 2021久久精品免费观看| 三级韩国一区久久二区综合| 污污内射久久一区二区欧美日韩| 久久综合久久美利坚合众国| 三级韩国一区久久二区综合 | 免费精品久久天干天干| 一本久道久久综合狠狠躁AV| 久久免费视频6| 精品久久久久成人码免费动漫| 97久久国产露脸精品国产| 精品久久久久久中文字幕大豆网| 亚洲国产成人久久综合一区77| 国产一区二区久久久| 久久亚洲精品国产亚洲老地址| 久久丫精品国产亚洲av| 亚洲人成精品久久久久| 亚洲AV无码久久寂寞少妇|