一. 什么是Lambda w+
!c9
所谓Lambda,简单的说就是快速的小函数生成。 I!*P' {lh
在C++中,STL的很多算法都要求使用者提供一个函数对象。例如for_each函数,会要求用户提供一个表明“行为”的函数对象。以vector<bool>为例,如果想使用for_each对其中的各元素全部赋值为true,一般需要这么一个函数对象, Su6kpC!EW
{] ]%0!n\
GEc-<`-
fGlvum
class filler v9:J 55x
{ 2[+.*Ef
public : pxTtV g.
void operator ()( bool & i) const {i = true ;} ;QXg*GNAv$
} ; <$z[pw<
bTimJp[b
}={@_g#
这样实现不但麻烦,而且不直观。而如果使用lambda,则允许用户使用一种直观和见解的方式来处理这个问题。以boost.lambda为例,刚才的问题可以这么解决: KqntOo}
y)
n~ad#iN
`~)?OTzU#
?DUim1KG
for_each(v.begin(), v.end(), _1 = true ); HZRFE[ 9nb
L?N&kzA
,W)DQwAg
那么下面,就让我们来实现一个lambda库。 MSS[-}
?YL JXq
B.5+!z&7
e3SnC:OWf
二. 战前分析 Az:~|P
首先要说明的是,我并没有读过boost.lambda或其他任何lambda库的代码,因此如代码有雷同,纯属巧合。
%lnkD5
开始实现以前,首先要分析出大致的实现手法。先让我们来看几段使用Lambda的代码 yM@sGz6c!
{ im?tZ,
V_J0I*Qa4
for_each(v.begin(), v.end(), _1 = 1 ); &!X<F,
/* --------------------------------------------- */ HAK,z0/
vector < int *> vp( 10 ); ^t4^gcoZ4Z
transform(v.begin(), v.end(), vp.begin(), & _1); ';FJs&=I
/* --------------------------------------------- */ wz`% (\
sort(vp.begin(), vp.end(), * _1 > * _2); piM4grg
\
/* --------------------------------------------- */ $TXiWW+
int b = * find_if(v.begin, v.end(), _1 >= 3 && _1 < 5 ); |hika`35K
/* --------------------------------------------- */ 3 k/E$wOj
for_each(vp.begin(), vp.end(), cout << * _1 << ' \n ' ); \[3~*eX6
/* --------------------------------------------- */ z)C/U
for_each(vp.begin(), vp.end(), cout << constant( ' \n ' ) << * _1); md+pS"8o;
yor'"6)i
<jV,VKL#
QNx]8r
看了之后,我们可以思考一些问题: }qECpKa0
1._1, _2是什么? 6}E>B{Y
显然_1和_2都满足C++对于标识符的要求,可见_1和_2都是对象。 yk?bz
2._1 = 1是在做什么? R%RbC!P
既然_1是一个对象,那么_1的类必然重载了operator=(int)。那么operator=返回什么呢?该函数所返回的对象被传入for_each的第3个参数,可见其返回了一个函数对象。现在整个流程就很清楚了。_1 = 1调用了operator=,其返回了一个函数对象,该函数对象能够将参数1赋值为1。 >JE+j=
Ok,回答了这两个问题之后,我们的思路就很清晰了。如果要实现operator=,那么至少要实现2个类,一个用于产生_1的对象,另一个用于代表operator=返回的函数对象。 n/1t UF
ik(YJw'i7E
gW~T{+f
三. 动工 cgrSd99.
首先实现一个能够范型的进行赋值的函数对象类: hE(R[hc
g}<jn'@{
C`;igg$t_
0(-4"u>?
template < typename T > CHKhJ v3+4
class assignment 8C*@d_=q
{ WBWW7 HK
T value; ]?=87w
public : "
7^nRJy
assignment( const T & v) : value(v) {} p\=T#lb
template < typename T2 > uG7]s]Wdz;
T2 & operator ()(T2 & rhs) const { return rhs = value; } $f3 IO#N
} ; <)T| HKx
?3BcjD0
o@L0ET
其中operator()被声明为模版函数以支持不同类型之间的赋值。 ?P0b/g
然后我们就可以书写_1的类来返回assignment #b;?:.m\=
w~6UOA8}
g0zzDv7~
Mrrpm%Y
class holder sr;&/l#7h
{ >ZOlSLu
public : BQPmo1B
template < typename T > gaz7u8$A=
assignment < T > operator = ( const T & t) const }2;P`s
{ b69nj
return assignment < T > (t); G"FO%3&|
} 7e+C5W*9b
} ; 0}<blU
Yt#;
+*d5
2@tnOs(*
由于该类是一个空类,因此我们可以在其后放心大胆的写上: phu,&DS!
8HKv_vl
static holder _1; !rRBy3&
Ok,现在一个最简单的lambda就完工了。你可以写 z9S
(<