一. 什么是Lambda s (PY/{8
所谓Lambda,简单的说就是快速的小函数生成。 \Ow,CUd
在C++中,STL的很多算法都要求使用者提供一个函数对象。例如for_each函数,会要求用户提供一个表明“行为”的函数对象。以vector<bool>为例,如果想使用for_each对其中的各元素全部赋值为true,一般需要这么一个函数对象, ~<O,Vs_C/
\+B?}P8N*l
JZx%J)
[X"k>
Sq
class filler VTw/_Hf2p
{ W<'<'z5
public : $$gtZ{ukQ
void operator ()( bool & i) const {i = true ;} 0s%6n5>
} ; hPO>,j^
P;U@y"s
>4)g4~'n!
这样实现不但麻烦,而且不直观。而如果使用lambda,则允许用户使用一种直观和见解的方式来处理这个问题。以boost.lambda为例,刚才的问题可以这么解决: YKx 1NC
Jt=>-Spj
Bymny>.M
5'
\)`
for_each(v.begin(), v.end(), _1 = true ); Y3oMh,
n<R \w''x
lX;mhJj!
那么下面,就让我们来实现一个lambda库。 e- 6(F4
#5{sglC"|F
i^/54
&oN/_7y
二. 战前分析 P\(30
首先要说明的是,我并没有读过boost.lambda或其他任何lambda库的代码,因此如代码有雷同,纯属巧合。 vInFo.e[4
开始实现以前,首先要分析出大致的实现手法。先让我们来看几段使用Lambda的代码 ,)$Wm-
Gpu_=9vzv
`]>on`n?
for_each(v.begin(), v.end(), _1 = 1 ); #"r kuDO
/* --------------------------------------------- */ Phlk1*1n
vector < int *> vp( 10 ); -1m vhR~
transform(v.begin(), v.end(), vp.begin(), & _1); !sK#zAR2
/* --------------------------------------------- */ {3 o%d:
sort(vp.begin(), vp.end(), * _1 > * _2); ND,`QjmZ
/* --------------------------------------------- */ O5MDGg
int b = * find_if(v.begin, v.end(), _1 >= 3 && _1 < 5 ); B$7[8h
/* --------------------------------------------- */ ^pw7o6}
for_each(vp.begin(), vp.end(), cout << * _1 << ' \n ' ); &;U|7l~vl
/* --------------------------------------------- */ FO^24p
for_each(vp.begin(), vp.end(), cout << constant( ' \n ' ) << * _1); $jcz?vH
=ZMF ]|
uu@<&.r\C
1.dX)^\
看了之后,我们可以思考一些问题: _LsYMUe
1._1, _2是什么? I}%mfojC
显然_1和_2都满足C++对于标识符的要求,可见_1和_2都是对象。 $Sw,hb
2._1 = 1是在做什么? E7LbSZ
既然_1是一个对象,那么_1的类必然重载了operator=(int)。那么operator=返回什么呢?该函数所返回的对象被传入for_each的第3个参数,可见其返回了一个函数对象。现在整个流程就很清楚了。_1 = 1调用了operator=,其返回了一个函数对象,该函数对象能够将参数1赋值为1。 JD-Becz
Ok,回答了这两个问题之后,我们的思路就很清晰了。如果要实现operator=,那么至少要实现2个类,一个用于产生_1的对象,另一个用于代表operator=返回的函数对象。 !7Uu]m69n
JU2P%3
ck~ '`<7
三. 动工 s
kY0 \V
首先实现一个能够范型的进行赋值的函数对象类: PHQcstW
w= B
SZE `J:w
&m4f1ZO*
template < typename T > vC-[#]<
class assignment V^WQ6G1
{ QU%N*bFW%P
T value; .Nk6
public : *V<)p%l.
assignment( const T & v) : value(v) {} 3l+|&q[v
template < typename T2 > 0@w&J9yG
T2 & operator ()(T2 & rhs) const { return rhs = value; } =x oBC&u
} ;
HFv?s
u{pTva
YpiRF+G
其中operator()被声明为模版函数以支持不同类型之间的赋值。 J]\s*,C&
然后我们就可以书写_1的类来返回assignment flPZlL
DbQBVy
fGG
9zB6
@21u I{
class holder x@Sra@
{ %Au T8
public : nE^wxtY
template < typename T > k=FcPF"
assignment < T > operator = ( const T & t) const pBvo M={2!
{ W*3o|x
return assignment < T > (t); Ipg\9*c`
} ,A^L=+
} ; &!4(
0u
% hNn%Oy:E
2-P I JO
由于该类是一个空类,因此我们可以在其后放心大胆的写上: @_(nd57oSs
EI<"DB
static holder _1; { .cB>L
Ok,现在一个最简单的lambda就完工了。你可以写 >*Sv0#
\2(MpB\_6!
for_each(v.begin(), v.end(), _1 = 1 ); Fr<Pe&d