青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 31  文章 - 128  trackbacks - 0
<2007年7月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

常用鏈接

留言簿(5)

隨筆分類(38)

隨筆檔案(31)

收藏夾(4)

College

High School

最新隨筆

搜索

  •  

積分與排名

  • 積分 - 56938
  • 排名 - 407

最新評論

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

閱讀排行榜

評論排行榜

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


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


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

 


九. 簡化
很明顯,要支持一個操作符所要做的工作太多了,而且在每個functor中申明result_1至
result_n,可見如果n發生變化,維護的開銷極大。
我們現在需要找到一個自動生成這種functor的方法。
首先,我們注意到result_x的形式很統一。對于各種操作符,其返回值無非下列幾種:
    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來執行運算符操作,很漂亮
比如要支持操作符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);
    }

有點長不是么?不過實際代碼量減少了很多,而且此后如果支持的參數上限發生變化,我們
就只需要修改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的執行就是執行傳進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 閱讀(1023) 評論(0)  編輯 收藏 引用 所屬分類: templateBoostC++
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲欧美国产制服动漫| 久久久免费观看视频| 亚洲专区在线| 亚洲一区免费| 性欧美8khd高清极品| 午夜精品视频网站| 欧美在线二区| 免费在线观看日韩欧美| 91久久久在线| 亚洲午夜在线观看| 久久久久九九视频| 欧美精品一区二区三区蜜桃 | 久热爱精品视频线路一| 久久久成人网| 亚洲美女av电影| 亚洲网站在线播放| 开元免费观看欧美电视剧网站| 老司机成人网| 国产精品日韩电影| av成人免费在线| 久久尤物视频| 国产亚洲美州欧州综合国| 亚洲激情视频| 久久久久综合网| 欧美一区二区大片| 欧美日韩国产综合新一区| 国产日韩欧美精品| 午夜欧美精品久久久久久久| 亚洲狼人精品一区二区三区| 久久成人免费网| 国精品一区二区三区| 亚洲欧美在线看| 亚洲一二三区精品| 国产精品蜜臀在线观看| 亚洲淫性视频| 亚洲一区免费| 在线播放亚洲一区| 欧美v国产在线一区二区三区| 久久av免费一区| 国产一区二区视频在线观看| 欧美一区二区视频在线| 欧美一区二区精品| 国产一区二区观看| 欧美成人免费播放| 欧美人交a欧美精品| 欧美国产在线观看| 亚洲国产91色在线| 欧美成人精品1314www| 老司机免费视频一区二区| 韩国一区二区三区美女美女秀| 久久国产精品久久w女人spa| 新狼窝色av性久久久久久| 国产一区二三区| 亚洲国产精品久久久久秋霞蜜臀| 欧美福利视频| 欧美亚洲一区二区在线观看| 看片网站欧美日韩| 欧美在线视频播放| 欧美国产日韩免费| 久久久久国产精品一区| 国产精品国码视频| 亚洲国产精品成人综合| 国产精品亚洲激情| 一区二区三区毛片| aa级大片欧美三级| 欧美日本一区二区视频在线观看| 久久久91精品国产一区二区三区| 欧美性一区二区| 亚洲桃色在线一区| 午夜视频在线观看一区二区| 欧美精品一区二区视频| 欧美v国产在线一区二区三区| 国产一区二区日韩精品| 亚洲女优在线| 久久人人看视频| 一区二区亚洲| 欧美高清视频| 亚洲激情女人| 亚洲欧美偷拍卡通变态| 国产精品久久久久国产精品日日| 一区二区毛片| 久久久久久久999| 美国十次成人| 美国成人毛片| 亚洲精品免费在线观看| 欧美片第一页| 欧美影院视频| 欧美成人中文字幕| 99国产精品久久久| 国产视频亚洲| 欧美成人精品1314www| 亚洲人成久久| 久久亚洲高清| 亚洲女性裸体视频| 亚洲第一免费播放区| 欧美伊人久久久久久久久影院| 国产在线拍揄自揄视频不卡99| 欧美激情视频一区二区三区免费 | 欧美日韩在线观看视频| 一区二区三区色| 欧美二区不卡| 蜜臀av性久久久久蜜臀aⅴ| 亚洲综合成人婷婷小说| 亚洲精品视频免费| 欧美a级片一区| 欧美专区福利在线| 亚洲欧美国产高清va在线播| 亚洲人成在线观看| 国产在线乱码一区二区三区| 国产日韩亚洲欧美精品| 国产精品观看| 国产亚洲福利一区| 国产亚洲欧美中文| 黑人极品videos精品欧美裸| 国产一区二区三区视频在线观看| 欧美日韩视频一区二区三区| 欧美激情一区在线| 欧美人成在线视频| 亚洲毛片一区二区| 一本大道av伊人久久综合| 亚洲日韩中文字幕在线播放| 91久久在线视频| 一区二区三区四区蜜桃| 亚洲一区亚洲二区| 久久久久一本一区二区青青蜜月| 久久久久国色av免费看影院| 欧美二区视频| 国产精品亚洲综合久久| 亚洲经典三级| 久久激情视频| 亚洲成人在线视频网站| 国内精品美女av在线播放| 亚洲人成欧美中文字幕| 久久久999成人| 亚洲素人在线| 欧美大秀在线观看| 国产日韩精品一区二区浪潮av| 亚洲国产欧美一区二区三区久久| 亚洲视频欧美在线| 欧美激情在线免费观看| 午夜电影亚洲| 国产欧美一区二区三区另类精品| 最新精品在线| 欧美成人免费小视频| 性欧美暴力猛交69hd| 国产麻豆日韩欧美久久| 亚洲欧美国产视频| 中文在线不卡视频| 久久国产欧美| 久久久天天操| 亚洲电影免费观看高清完整版在线| 欧美亚洲日本国产| 激情综合网激情| 欧美精品aa| 中文在线不卡| 欧美一级欧美一级在线播放| 国产亚洲一区精品| 欧美激情影院| 国产精品久久国产精麻豆99网站| 亚洲日本中文字幕区| 亚洲老司机av| 亚洲黄色在线观看| 欧美日韩激情小视频| 日韩午夜av电影| 久久美女性网| 亚洲欧美成人在线| 国产精品啊v在线| 亚洲精品国产精品乱码不99| 一区免费观看| 久久综合色影院| 免费亚洲电影在线观看| 国产日韩欧美视频| 亚洲日本中文字幕区| 国产欧美精品在线观看| 日韩亚洲欧美一区| 亚洲精选91| 欧美jizz19hd性欧美| 久久免费视频一区| 国产精品亚洲综合一区在线观看| 欧美激情a∨在线视频播放| 国产一区二区高清视频| 欧美在线地址| 久久久久国色av免费看影院 | 美女视频黄免费的久久| 欧美日韩在线看| 99这里只有精品| 亚洲综合导航| 国内精品久久久久久久影视蜜臀| 一区二区三区av| 欧美在线观看网站| 亚洲国产99精品国自产| 欧美色另类天堂2015| 亚洲一卡久久| 欧美不卡视频| 亚洲一区黄色| 亚洲人体1000| 国产欧美日韩亚洲| 久久五月激情| 亚久久调教视频| 日韩午夜在线|