一. 什么是Lambda T*{nf
所谓Lambda,简单的说就是快速的小函数生成。 0BrAgv"3a_
在C++中,STL的很多算法都要求使用者提供一个函数对象。例如for_each函数,会要求用户提供一个表明“行为”的函数对象。以vector<bool>为例,如果想使用for_each对其中的各元素全部赋值为true,一般需要这么一个函数对象, %CIRN}
3%L@=q
><wYk)0E
O6"S=o&
class filler 6%a:^f]
{ *bSxobn
public : <c.8f;1F
void operator ()( bool & i) const {i = true ;} gGE&}EoLU
} ; P$#{a2
SX]uIkw
!g7lJ\B
这样实现不但麻烦,而且不直观。而如果使用lambda,则允许用户使用一种直观和见解的方式来处理这个问题。以boost.lambda为例,刚才的问题可以这么解决: 1LVO0lT
zff<#yK1
QWI)Y:<K/
vf;&0j&`
for_each(v.begin(), v.end(), _1 = true ); bae\EaS
?
2(i|n=
?k$'po*Eq
那么下面,就让我们来实现一个lambda库。 F[)5A5+:Y
b6UpE`\z
9Q>85IiT
vHXCT?FuG
二. 战前分析
8/s?Gz
首先要说明的是,我并没有读过boost.lambda或其他任何lambda库的代码,因此如代码有雷同,纯属巧合。 _b"K,[0o
开始实现以前,首先要分析出大致的实现手法。先让我们来看几段使用Lambda的代码 pD17r}%
6wq>&P5
+SNjU"x
for_each(v.begin(), v.end(), _1 = 1 ); %:}o\ _w
/* --------------------------------------------- */ VRB!u420
vector < int *> vp( 10 ); K_ Od u^
transform(v.begin(), v.end(), vp.begin(), & _1); v3b+Ddp
/* --------------------------------------------- */ e!=~f%c<N
sort(vp.begin(), vp.end(), * _1 > * _2); <j}A=SDZ)
/* --------------------------------------------- */ He*c=^8k
int b = * find_if(v.begin, v.end(), _1 >= 3 && _1 < 5 ); ]Ns)fr6
/* --------------------------------------------- */ xG WA5[YV
for_each(vp.begin(), vp.end(), cout << * _1 << ' \n ' ); YL&)@h
/* --------------------------------------------- */ Q!y%N&
for_each(vp.begin(), vp.end(), cout << constant( ' \n ' ) << * _1); 2rxz<ck(
&4{!5r
~@$RX:p
Sjp ]TWj
看了之后,我们可以思考一些问题: \b*z<Odv
1._1, _2是什么? "A]#KTP
显然_1和_2都满足C++对于标识符的要求,可见_1和_2都是对象。 yJ4ZB/ZQ
2._1 = 1是在做什么? L*FQ`:lZ
既然_1是一个对象,那么_1的类必然重载了operator=(int)。那么operator=返回什么呢?该函数所返回的对象被传入for_each的第3个参数,可见其返回了一个函数对象。现在整个流程就很清楚了。_1 = 1调用了operator=,其返回了一个函数对象,该函数对象能够将参数1赋值为1。 y.$Ae1a=
Ok,回答了这两个问题之后,我们的思路就很清晰了。如果要实现operator=,那么至少要实现2个类,一个用于产生_1的对象,另一个用于代表operator=返回的函数对象。 8/k"A-m
gC+?5_=<
^X;p8uBo
三. 动工 6aKfcvf &
首先实现一个能够范型的进行赋值的函数对象类: nc^DFP
fS$;~@p
:i>If:>g
HCw,bRxm
template < typename T > h+ <Jv
class assignment ckYT69U
{ L+8{%\UPd
T value; *WfQi8
public : `\$EPUM
assignment( const T & v) : value(v) {} MdDL?ev
template < typename T2 > \V#fl
T2 & operator ()(T2 & rhs) const { return rhs = value; } oA?EJ ~%
} ; #z+?t
m5v IS
;;|.qgxc~
其中operator()被声明为模版函数以支持不同类型之间的赋值。 R PdFLC/
然后我们就可以书写_1的类来返回assignment :%>)S
3sD|R{
1:!H`*DU&
m*.+9 6
class holder _:]g:F[
#
{ c2gi3
public : %j@@J\G!
template < typename T > ;0lY_ii
assignment < T > operator = ( const T & t) const G#fF("Ndu`
{ jyB
Ys& v
return assignment < T > (t); _#qfe
} ;I?x;lH
} ; l b;P&V
E=Vp%08(
L1Jn@
由于该类是一个空类,因此我们可以在其后放心大胆的写上: )|/%]@` N
g`C\pdX"B
static holder _1; <eZ*LK?
Ok,现在一个最简单的lambda就完工了。你可以写 [HI$[:[
U!(es0rX
for_each(v.begin(), v.end(), _1 = 1 ); ~ dk9 7Z8
而不用手动写一个函数对象。 qw
03]a
~F8xXW0
wXtp(YwlH
Y,Lx6kU
四. 问题分析 2 w6iqLr?
虽然基本上一个Lambda已经初步实现出来了,但是仔细想想,问题也是很多的。 &M: