• <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
            <2007年11月>
            28293031123
            45678910
            11121314151617
            18192021222324
            2526272829301
            2345678

            常用鏈接

            留言簿(5)

            隨筆分類(38)

            隨筆檔案(31)

            收藏夾(4)

            College

            High School

            最新隨筆

            搜索

            •  

            積分與排名

            • 積分 - 55895
            • 排名 - 407

            最新評論

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

            閱讀排行榜

            評論排行榜

            發(fā)信人: shifan (家沒有豚豚 T.T), 板面: C++
            標  題: 如何實現Lambda[第二部分]
            發(fā)信站: 飄渺水云間 (Thu Jun  8 23:30:20 2006), 轉信


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


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

             


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

            OK,這樣我們將返回值類型總結為以上8種,就可以將各種result_x從functor中剝離出來了

            例如針對第一條,我們實現一個policy類:
                

            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是一個將一個類型轉為其非引用形式的trait

            下面我們來剝離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)]


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

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

                }
            ;


            這個工作可以讓宏來做:

                 #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)
            來申明meta_divide。同樣還可以申明宏DECLARE_META_UNY_PRE_FUNC和
            DECLARE_META_UNY_POST_FUNC來產生單目前綴和后綴操作符的函數
            (ps.我本堅持該lambda實現不使用宏的,但是在這種小劑量的又很一致的代碼面前,使用
            宏實在是很誘人。。。)


            下面就是要把operator()和result_x拼湊起來,形成一個我們要的functor,下面是一個單目
            的functor的實現體

                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));
                        }

                }
            ;

            同樣還可以申明一個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, 也就擁有了該類所定一個全部
            result_x, 同時使用FuncType來執(zhí)行運算符操作,很漂亮
            比如要支持操作符operator+,則需要寫一行
                DECLARE_META_BIN_FUNC(+, add, T1)
            那么binary_op<Left, Right, value_return, meta_add>就自然是operator+(雙目)的
            functor,不需要自己手動實現。
            停!不要陶醉在這美妙的幻覺中!
            如果把這段代碼拿到VC7或VC8下編譯,你會得到很有趣的結果。。。
            好了,這不是我們的錯,但是確實我們應該解決它。
            這實際上是vc的bug,解決方法是不要去使用typename Rettype::template result_2<T1,
            T2>::result_type這樣的形式。(感謝vbvan)
            下面是修改過的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,而自己申明一個對應的result_x做一次中轉,雖
            然其實毫無意義,卻恰好避開了vc的bug
            好啦,現在才真正完美了。
            現在在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);
                }

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

             


            十.    bind
            既然都做到這份上了,我們順便把bind也做了吧,其實事情已經變得很簡單了。
            先來分析一下一段例子

            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

             

            可見bind是一系列重載函數,返回某種functor,該functor的執(zhí)行就是執(zhí)行傳進bind的函數
            指針并正確的確定參數。
            我們來寫個簡單的。
            首先要知道一個函數的返回類型,我們使用一個trait來實現:
            對于函數對象類的版本:

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


            對于無參數函數的版本:

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


            對于單參數函數的版本:

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


            對于雙參數函數的版本:

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


            等等。。。
            然后我們就可以仿照value_return寫一個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;
                    }
            ;
                }
            ;

            最后一個單參數binder就很容易寫出來了

                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));
                    }

                }
            ;

            一目了然不是么?
            最后實現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個以上參數的bind可以同理實現。
            另外還可以照樣實現一系列binder來綁定類成員函數/變量,手法雷同,就不詳細介紹了。

             

             

             


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

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


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

            functor, 最后2個functor用operator, 生成一個新的functor
            operator,的實現這里略過了,請參照前面的描述。
            那么我們就照著這個思路來實現吧:

                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個參數的operator().
            代碼很清晰,但是還是讓我來解釋一下為什么要用int作為返回類型。
            其實對于do-while語義,返回類型是無意義的,然而將其定義為void會影響在某些情況下
            return的簡潔性,因為return一個void是不合法的。
            因此我們將其定為int,并返回0,這樣減少了其它地方編碼的復雜度。
            下面就是產生這個functor的類:

                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 ;
                }
            ;

            簡單吧,注意到這個while_函數,它自動的生成了一個do_while對象。
            最后,是那個do_

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

                }
            do_;


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

            ※ 來源:·飄渺水云間 freecity.cn·[FROM: shifan]                                                                       

            posted on 2006-07-15 15:32 shifan3 閱讀(991) 評論(0)  編輯 收藏 引用 所屬分類: templateBoostC++
            综合人妻久久一区二区精品| 久久精品无码午夜福利理论片| 麻豆国内精品久久久久久| 三级韩国一区久久二区综合| 久久无码中文字幕东京热| 久久九九久精品国产免费直播| 91精品国产91久久久久久蜜臀| 精品国产91久久久久久久a| 2021国内精品久久久久久影院| 亚洲午夜精品久久久久久人妖| 亚洲国产成人久久精品99| 超级碰久久免费公开视频| 2021国产精品久久精品| 天天综合久久久网| 日产精品久久久久久久| 久久99精品久久久久久野外| 久久精品a亚洲国产v高清不卡| 久久午夜福利无码1000合集| 国产亚洲美女精品久久久久狼| 亚洲精品NV久久久久久久久久| 国产AV影片久久久久久 | 国产巨作麻豆欧美亚洲综合久久| 久久影院综合精品| 亚洲色欲久久久综合网| 久久天天躁狠狠躁夜夜躁2014| 亚洲性久久久影院| 91久久福利国产成人精品| 91精品国产9l久久久久| 无码超乳爆乳中文字幕久久| 精品永久久福利一区二区| 国产产无码乱码精品久久鸭| 69SEX久久精品国产麻豆| 精品精品国产自在久久高清| 狠狠色丁香久久综合五月| 久久香蕉国产线看观看精品yw| 热久久最新网站获取| 久久精品人人做人人爽97| 精品精品国产自在久久高清| 国产精品热久久毛片| 久久99国产精品久久99小说| 亚洲AV日韩精品久久久久|