一. 什么是Lambda +aJ>rR
所谓Lambda,简单的说就是快速的小函数生成。 R%{a1r>9h
在C++中,STL的很多算法都要求使用者提供一个函数对象。例如for_each函数,会要求用户提供一个表明“行为”的函数对象。以vector<bool>为例,如果想使用for_each对其中的各元素全部赋值为true,一般需要这么一个函数对象, Rtb7|
K@sV\"U(*E
,24p%KJ*X
{{B%f.
class filler ix([mQg
{ zfc'=ODX
public : wj,:"ESb4
void operator ()( bool & i) const {i = true ;} Yn@lr6s
} ; :K-~fA%kt?
fuWO*
W yB3ls~
这样实现不但麻烦,而且不直观。而如果使用lambda,则允许用户使用一种直观和见解的方式来处理这个问题。以boost.lambda为例,刚才的问题可以这么解决: qu-B|
MuOa
PMNjn9d
)CuZDf@
N):tOD@B
for_each(v.begin(), v.end(), _1 = true ); $*AYcy7
o$#G0}yn
-&3hEv5
那么下面,就让我们来实现一个lambda库。 +_; l|uhT;
8.XoVW#
X.Rb-@
`}(b2Hc>
二. 战前分析 Jz7!4mu
首先要说明的是,我并没有读过boost.lambda或其他任何lambda库的代码,因此如代码有雷同,纯属巧合。 e8pG"`wM8
开始实现以前,首先要分析出大致的实现手法。先让我们来看几段使用Lambda的代码 F ~^Jmp7Y
qyF{f8pzq
luo
for_each(v.begin(), v.end(), _1 = 1 ); vd[}Gd
/* --------------------------------------------- */ ]~aF2LJ_q
vector < int *> vp( 10 ); 8vMG5#U[
transform(v.begin(), v.end(), vp.begin(), & _1); -*$HddD
/* --------------------------------------------- */ ^su<uG<R
sort(vp.begin(), vp.end(), * _1 > * _2); jzDuE{
/* --------------------------------------------- */ ;nodjbr,j
int b = * find_if(v.begin, v.end(), _1 >= 3 && _1 < 5 ); tKuVQH~D
/* --------------------------------------------- */ ToJ$A`_!`
for_each(vp.begin(), vp.end(), cout << * _1 << ' \n ' ); z.kvX+7'
/* --------------------------------------------- */ b6U2GDm\s
for_each(vp.begin(), vp.end(), cout << constant( ' \n ' ) << * _1); Y&S24aql
#:[t^}
[<%H>S1
^lA=* jY(
看了之后,我们可以思考一些问题: hEBY8=gK
1._1, _2是什么? mS^tX i5hg
显然_1和_2都满足C++对于标识符的要求,可见_1和_2都是对象。 KVT-P};jy*
2._1 = 1是在做什么? A/u)# ^\
既然_1是一个对象,那么_1的类必然重载了operator=(int)。那么operator=返回什么呢?该函数所返回的对象被传入for_each的第3个参数,可见其返回了一个函数对象。现在整个流程就很清楚了。_1 = 1调用了operator=,其返回了一个函数对象,该函数对象能够将参数1赋值为1。 zG ^$"f2
Ok,回答了这两个问题之后,我们的思路就很清晰了。如果要实现operator=,那么至少要实现2个类,一个用于产生_1的对象,另一个用于代表operator=返回的函数对象。 ?AJKBW^
7*
yzEM
*~t6(v?
三. 动工 4)@mSSfn.
首先实现一个能够范型的进行赋值的函数对象类: WU
quN
X$ s:>[H
t=Xv;=daB
umiBj)r
template < typename T > E%rk[wI
class assignment ;$smH=I
{ d8[J@M53|T
T value; q1QL@Ax
public : \P.I)n`8 y
assignment( const T & v) : value(v) {} X~lVVBO
template < typename T2 > h| ,:e;>}
T2 & operator ()(T2 & rhs) const { return rhs = value; } 6LalW5I
} ; BI3@|,._N
RloK,bg
n?- })
其中operator()被声明为模版函数以支持不同类型之间的赋值。 {so`/EWa
然后我们就可以书写_1的类来返回assignment &Xf^Iu
3BtaH#ZY
bn!HUM,
l|kSsP:GO
class holder H."EUcE{
{ d-k%{eBV
public : {]:7bV#JP
template < typename T > U)E(`{p]
assignment < T > operator = ( const T & t) const >8k_n
{ qU#1i:(F*
return assignment < T > (t); R)QC)U
} .(^ ,z&
} ; f33 l$pOp
- `p4-J!Fy
] Hzt b
由于该类是一个空类,因此我们可以在其后放心大胆的写上: L*&p!
IIn"=g=9
static holder _1; xa <UM5eI
Ok,现在一个最简单的lambda就完工了。你可以写 n)^i/ nXb'
uI1q>[
for_each(v.begin(), v.end(), _1 = 1 ); XCU7xi$d
而不用手动写一个函数对象。 w8U&ls