一. 什么是Lambda =j~vL`d2]
所谓Lambda,简单的说就是快速的小函数生成。 a;h.I}*]
在C++中,STL的很多算法都要求使用者提供一个函数对象。例如for_each函数,会要求用户提供一个表明“行为”的函数对象。以vector<bool>为例,如果想使用for_each对其中的各元素全部赋值为true,一般需要这么一个函数对象, |[W7&@hF
ccY! OSae
:Ldx^UO
0@tN3u?dx
class filler v;o/M6GL5
{ MJ M<
public : *~\R0ddz
void operator ()( bool & i) const {i = true ;} [e`e bn[C
} ; )>]@@Trx
YHOo6syk
M~ku4ZP
这样实现不但麻烦,而且不直观。而如果使用lambda,则允许用户使用一种直观和见解的方式来处理这个问题。以boost.lambda为例,刚才的问题可以这么解决: 0a}a
@~CXnc0
P;U(2;9 N
)Y &RMYy
for_each(v.begin(), v.end(), _1 = true ); I /z`)
fc<~R
>]<4t06D
那么下面,就让我们来实现一个lambda库。 UJiy]y
!dV2:`|+
@#2KmM~I
xO{$6M3-~
二. 战前分析 z=6zc-$y 9
首先要说明的是,我并没有读过boost.lambda或其他任何lambda库的代码,因此如代码有雷同,纯属巧合。 !T"jvDYH
开始实现以前,首先要分析出大致的实现手法。先让我们来看几段使用Lambda的代码 IwVdx^9
H(gETRh
ae>B0#=
for_each(v.begin(), v.end(), _1 = 1 ); `LOW)|6r`
/* --------------------------------------------- */ sXwa`_{
vector < int *> vp( 10 ); F#)@ c
transform(v.begin(), v.end(), vp.begin(), & _1); '\% Kd+k
/* --------------------------------------------- */ E}g)q;0v|2
sort(vp.begin(), vp.end(), * _1 > * _2); @q"HZO[
/* --------------------------------------------- */ y#{v\h
Cz
int b = * find_if(v.begin, v.end(), _1 >= 3 && _1 < 5 ); _KJ!C!
/* --------------------------------------------- */ `kYcTFk
for_each(vp.begin(), vp.end(), cout << * _1 << ' \n ' ); s3[\&zt
/* --------------------------------------------- */ se@?:n1)
for_each(vp.begin(), vp.end(), cout << constant( ' \n ' ) << * _1); |"
ag'h
U[{vA6
V [Wo9Y\
a7}O.NDf
看了之后,我们可以思考一些问题: yHf:/8Z
1._1, _2是什么? ~7>D>!!
显然_1和_2都满足C++对于标识符的要求,可见_1和_2都是对象。 O_ d[{e=5`
2._1 = 1是在做什么? g`(3r
既然_1是一个对象,那么_1的类必然重载了operator=(int)。那么operator=返回什么呢?该函数所返回的对象被传入for_each的第3个参数,可见其返回了一个函数对象。现在整个流程就很清楚了。_1 = 1调用了operator=,其返回了一个函数对象,该函数对象能够将参数1赋值为1。 c<ORmg6
Ok,回答了这两个问题之后,我们的思路就很清晰了。如果要实现operator=,那么至少要实现2个类,一个用于产生_1的对象,另一个用于代表operator=返回的函数对象。 dwqR,|
\IP
9EF A
uH |:gF^
三. 动工 P?hB`5X
首先实现一个能够范型的进行赋值的函数对象类: %W^Zob
?k^~qlye
?UV|m
b ;>?m
template < typename T > ML.|\:r*
class assignment Nj{;
{ 0{(5J,/BF
T value; oTg
'N
public : dC>(UDC
assignment( const T & v) : value(v) {} ,Bs/.htQj
template < typename T2 > tz9"#=}0
T2 & operator ()(T2 & rhs) const { return rhs = value; } tu' s]3RE
} ; 4hx4/5[^
6w4HJZF~
)lU9\"?o
其中operator()被声明为模版函数以支持不同类型之间的赋值。 o]DYS,v
然后我们就可以书写_1的类来返回assignment 30W.ks5(
CrB4%W:{
g&rz*)|/
NwN3T]W
class holder @77+K:9I7
{ g?N^9B,$2
public : t=fr`|!
template < typename T > Zi}jf25
assignment < T > operator = ( const T & t) const E:y^= Y
{ !j/54,
return assignment < T > (t); -TS5g1
} ,AH2/^:%c
} ; mNOxe
XXA.wPD-
0ev='v8?
由于该类是一个空类,因此我们可以在其后放心大胆的写上: av bup
j&[u$P*K
static holder _1; ~KczP1p
Ok,现在一个最简单的lambda就完工了。你可以写 pM9M8d
]app 9
for_each(v.begin(), v.end(), _1 = 1 ); ji
C2B
而不用手动写一个函数对象。
"u)e,gu
$Lz!04
=fJ /6
&