一. 什么是Lambda o[g]Va*8
所谓Lambda,简单的说就是快速的小函数生成。 )!5"\eys
在C++中,STL的很多算法都要求使用者提供一个函数对象。例如for_each函数,会要求用户提供一个表明“行为”的函数对象。以vector<bool>为例,如果想使用for_each对其中的各元素全部赋值为true,一般需要这么一个函数对象, 2
;Q|h$n
# (-?i\i
oTveY
UW&K\P
class filler Mr@{3do$
{ c
LfPSA
public : ootkf=
void operator ()( bool & i) const {i = true ;} 1$ENNq#0
} ; -Zqw[2Q4
K*5Ij]j&
Y r8gKhv W
这样实现不但麻烦,而且不直观。而如果使用lambda,则允许用户使用一种直观和见解的方式来处理这个问题。以boost.lambda为例,刚才的问题可以这么解决: /U="~{*-R
e'~<uN>
W,.Exh
c#a>> V
for_each(v.begin(), v.end(), _1 = true ); y27MG
+u3vKzD
70Ei<
那么下面,就让我们来实现一个lambda库。 @1V?94T1
}BiA@n,
9Yji34eDZ
k"+/DK,:
二. 战前分析 ?$=Ml$
首先要说明的是,我并没有读过boost.lambda或其他任何lambda库的代码,因此如代码有雷同,纯属巧合。 h4c4!S
开始实现以前,首先要分析出大致的实现手法。先让我们来看几段使用Lambda的代码 @e+qe9A|
\j0016;
nr%P11U\c
for_each(v.begin(), v.end(), _1 = 1 ); *a`_,Q{x
/* --------------------------------------------- */ FB
O_B
vector < int *> vp( 10 ); wdRk+
transform(v.begin(), v.end(), vp.begin(), & _1); pZ 7KWk4
/* --------------------------------------------- */ |^O3~!JP(>
sort(vp.begin(), vp.end(), * _1 > * _2); hn e}G._b
/* --------------------------------------------- */ JR|P]}
int b = * find_if(v.begin, v.end(), _1 >= 3 && _1 < 5 ); l>pnY%(A
/* --------------------------------------------- */ M aP -
for_each(vp.begin(), vp.end(), cout << * _1 << ' \n ' ); 4TcW%
/* --------------------------------------------- */ p%5(Qqmlk
for_each(vp.begin(), vp.end(), cout << constant( ' \n ' ) << * _1); p+Fh9N<F9
rrl{3
?
WB" 90!
hmv*IF.
看了之后,我们可以思考一些问题: D\ P-|}
1._1, _2是什么? BWzo|isv
显然_1和_2都满足C++对于标识符的要求,可见_1和_2都是对象。 GX N:=
2._1 = 1是在做什么? Z
)X(
既然_1是一个对象,那么_1的类必然重载了operator=(int)。那么operator=返回什么呢?该函数所返回的对象被传入for_each的第3个参数,可见其返回了一个函数对象。现在整个流程就很清楚了。_1 = 1调用了operator=,其返回了一个函数对象,该函数对象能够将参数1赋值为1。 >n5Kz]]%
Ok,回答了这两个问题之后,我们的思路就很清晰了。如果要实现operator=,那么至少要实现2个类,一个用于产生_1的对象,另一个用于代表operator=返回的函数对象。 l'?(4N
q ;e/gP2
@Dd3mWKq
三. 动工 oMKG M@V
首先实现一个能够范型的进行赋值的函数对象类: WISeP\:^
IDp2#qg_
hlHle\[ds
MYUL y2)
template < typename T > muKjeg'b
class assignment (~^KXJ{->
{ $ ~/x;z:
T value; n0w0]dJ&lc
public : 2l +t-
assignment( const T & v) : value(v) {} sfC/Q"Zs
template < typename T2 > kj`h{Wc[)
T2 & operator ()(T2 & rhs) const { return rhs = value; } T>m|C}yy
} ; 1fV\84m^
oi%IHX(`
xgWVxX^)
其中operator()被声明为模版函数以支持不同类型之间的赋值。 D}?JX5.
然后我们就可以书写_1的类来返回assignment t=n@<1d
'^BTa6W}m
{QT:1U\.
sl*&.F,v=
class holder tS[@?qP
{ 1pTQMf a
public : w=ZK=@
template < typename T > 5-"aK~@+
assignment < T > operator = ( const T & t) const j`-9.
{ 67 wq8|
return assignment < T > (t); kQ .3J.Q5
} !D9V9p
} ; 78E<_UgcB
}nWW`:t kx
W<H<~wf#
由于该类是一个空类,因此我们可以在其后放心大胆的写上: P,7beHjf
$WbfRyXi7'
static holder _1; %Pk@`t (3
Ok,现在一个最简单的lambda就完工了。你可以写 }M${ _D
NJ(H$tB@
for_each(v.begin(), v.end(), _1 = 1 ); YF13&E2`\
而不用手动写一个函数对象。 CjU?3Ag
oTf^-29d
=Ka :i>
XI5q>cd\Sz
四. 问题分析 e;&f