一. 什么是Lambda tl><"6AIP
所谓Lambda,简单的说就是快速的小函数生成。 <<i3r|}
在C++中,STL的很多算法都要求使用者提供一个函数对象。例如for_each函数,会要求用户提供一个表明“行为”的函数对象。以vector<bool>为例,如果想使用for_each对其中的各元素全部赋值为true,一般需要这么一个函数对象, ap{2$k ,
O9g{+e`
\[jq4`\$
D5:{fWVsV/
class filler 7}vg.hmZ
{ @DZB9DDR
public : CT1ja.\;
void operator ()( bool & i) const {i = true ;} 2AtLyN'.
} ; jK' N((Hz
^D<r
Ur5FC r
这样实现不但麻烦,而且不直观。而如果使用lambda,则允许用户使用一种直观和见解的方式来处理这个问题。以boost.lambda为例,刚才的问题可以这么解决: Zc!@0
e'=MQ,EWd
+3&zN(
qA!]E^0*Ke
for_each(v.begin(), v.end(), _1 = true ); ei6AV1| p
h;-yU.(w
q+[SbG&
那么下面,就让我们来实现一个lambda库。 H)>@/"j;
#(1j#\
b*FC\:\
Le*.*\
二. 战前分析 59#lU~Kv
首先要说明的是,我并没有读过boost.lambda或其他任何lambda库的代码,因此如代码有雷同,纯属巧合。 ?gwUwOV"
开始实现以前,首先要分析出大致的实现手法。先让我们来看几段使用Lambda的代码 !vk|<P1
mWyqG*-Hb
#vzEu
)Ul
for_each(v.begin(), v.end(), _1 = 1 ); !YP@m~
/* --------------------------------------------- */ n_B"-n
vector < int *> vp( 10 ); La@
+>
transform(v.begin(), v.end(), vp.begin(), & _1); }sx_Yj
/* --------------------------------------------- */ hAm`NJMSO
sort(vp.begin(), vp.end(), * _1 > * _2); I8QjKI (
/* --------------------------------------------- */ l983vKr
int b = * find_if(v.begin, v.end(), _1 >= 3 && _1 < 5 ); %/>Y/!;
/* --------------------------------------------- */ 9JWa$iBH@
for_each(vp.begin(), vp.end(), cout << * _1 << ' \n ' ); Rcawc
Y
/* --------------------------------------------- */ JXw^/Y$
for_each(vp.begin(), vp.end(), cout << constant( ' \n ' ) << * _1); ~j-cS
J3
#Jna6
HmZ{L +"
uio@r^Xz
看了之后,我们可以思考一些问题: KL ?@@7
1._1, _2是什么? :Dd$i_3=
显然_1和_2都满足C++对于标识符的要求,可见_1和_2都是对象。 +n7?S~R$
2._1 = 1是在做什么? l27\diKPJ
既然_1是一个对象,那么_1的类必然重载了operator=(int)。那么operator=返回什么呢?该函数所返回的对象被传入for_each的第3个参数,可见其返回了一个函数对象。现在整个流程就很清楚了。_1 = 1调用了operator=,其返回了一个函数对象,该函数对象能够将参数1赋值为1。 TuW/N
L|
Ok,回答了这两个问题之后,我们的思路就很清晰了。如果要实现operator=,那么至少要实现2个类,一个用于产生_1的对象,另一个用于代表operator=返回的函数对象。 1Jj Y!
CEC
nq3
YFTjPBV
三. 动工 w=}uwvn NX
首先实现一个能够范型的进行赋值的函数对象类: Nr0
(E
9{$'S4
HFq m6|
4<x'ocKlD
template < typename T > /'hC i]b@v
class assignment \T;\XAGr
{ ru`U'
T value; 9W8]8sUeG
public : nN~~cV
assignment( const T & v) : value(v) {} gN>2xnh'm
template < typename T2 > r@{~ 5&L
T2 & operator ()(T2 & rhs) const { return rhs = value; } ^+
wD43
} ; r)T:7zy
W;1|+6x
Q0\0f
其中operator()被声明为模版函数以支持不同类型之间的赋值。 jn:NYJv
然后我们就可以书写_1的类来返回assignment @G:V
Hk7q{`:N
zz^F
k&
5P .qXA"D
class holder >j{z>
{ 6&!&\
public : &*s0\
8
template < typename T > !bC+TYsU
assignment < T > operator = ( const T & t) const (oJ9k[(
{ `juLQH
return assignment < T > (t); .>(Q)"v
} 1RKW2RCaW_
} ; :0/q5_t
< Z|Ep1W
oxj3[</'k
由于该类是一个空类,因此我们可以在其后放心大胆的写上: a"av#Y
i_kE^SSgm
static holder _1; 0I{gJSK.,
Ok,现在一个最简单的lambda就完工了。你可以写 xP=/N!,#
](B@5-^
for_each(v.begin(), v.end(), _1 = 1 ); $O{duJU
而不用手动写一个函数对象。 s!9dQ.
|8bq>01~
fgj^bcp-
'<R>E:5
四. 问题分析 !6G?zipB
虽然基本上一个Lambda已经初步实现出来了,但是仔细想想,问题也是很多的。 j&