一. 什么是Lambda K
6,c||#<
所谓Lambda,简单的说就是快速的小函数生成。 .SSPJY(
在C++中,STL的很多算法都要求使用者提供一个函数对象。例如for_each函数,会要求用户提供一个表明“行为”的函数对象。以vector<bool>为例,如果想使用for_each对其中的各元素全部赋值为true,一般需要这么一个函数对象, d(|4 +^>
5-S-r9
`FX?P`\@I
-Hy>
z
class filler *e<'|Kq
{ %>y!N!.F
public : VMNdC}
void operator ()( bool & i) const {i = true ;} J&+"
} ; 2^U?Ztth6
Xd1+?2
~L>&p
这样实现不但麻烦,而且不直观。而如果使用lambda,则允许用户使用一种直观和见解的方式来处理这个问题。以boost.lambda为例,刚才的问题可以这么解决: ??++0<75
Gvr>n@n
'] _7Xa'
.t{uzDM
for_each(v.begin(), v.end(), _1 = true ); N%u4uLP5k
t$R0UprK
GSH,;cY
那么下面,就让我们来实现一个lambda库。 vB5mOXGN q
[?g}<fa
pK/RkA1
#sbW^Q'I
二. 战前分析 %L-{4Z!"sI
首先要说明的是,我并没有读过boost.lambda或其他任何lambda库的代码,因此如代码有雷同,纯属巧合。 w[EEA_\
开始实现以前,首先要分析出大致的实现手法。先让我们来看几段使用Lambda的代码 n-<`Z NMU
T ~p>Ed 9
ma"M? aM
for_each(v.begin(), v.end(), _1 = 1 ); A v;NQt8ut
/* --------------------------------------------- */ 1 7iw`@
vector < int *> vp( 10 ); %uo#<Ny/ I
transform(v.begin(), v.end(), vp.begin(), & _1); c^5fhmlt
/* --------------------------------------------- */ twa H20
sort(vp.begin(), vp.end(), * _1 > * _2); 2&AX_#P
/* --------------------------------------------- */ Q2Uk0:M
int b = * find_if(v.begin, v.end(), _1 >= 3 && _1 < 5 ); <YCR^?hJSi
/* --------------------------------------------- */ i=fhK~Jd
for_each(vp.begin(), vp.end(), cout << * _1 << ' \n ' ); gxC`Ml
/* --------------------------------------------- */ :z|$K^)7Z
for_each(vp.begin(), vp.end(), cout << constant( ' \n ' ) << * _1); W4h ]4X
sp0_f;bC
)_?H BTG
UCo<ie\V
看了之后,我们可以思考一些问题: b8$%=Xp
1._1, _2是什么? K;TTGK
显然_1和_2都满足C++对于标识符的要求,可见_1和_2都是对象。 (@O,U
2._1 = 1是在做什么? yC!>7@m
既然_1是一个对象,那么_1的类必然重载了operator=(int)。那么operator=返回什么呢?该函数所返回的对象被传入for_each的第3个参数,可见其返回了一个函数对象。现在整个流程就很清楚了。_1 = 1调用了operator=,其返回了一个函数对象,该函数对象能够将参数1赋值为1。 D?H|O[
Ok,回答了这两个问题之后,我们的思路就很清晰了。如果要实现operator=,那么至少要实现2个类,一个用于产生_1的对象,另一个用于代表operator=返回的函数对象。 Us>
+|4olK$[
!&v"+ K3lU
三. 动工 9R&.$5[W(s
首先实现一个能够范型的进行赋值的函数对象类: |;U3pq)
eV0eMDY5
*;lb<uLv
xz7CnW1
template < typename T > RGY#0 .Z}
class assignment bPl'?3
{ (F:|tiV+
T value; !wro7ilMB
public : jd`]]FAww
assignment( const T & v) : value(v) {} _~*ba+{
template < typename T2 > 7&V3f=aj6
T2 & operator ()(T2 & rhs) const { return rhs = value; } x3jjtjf
} ; ye| 2gH
=Prz|
E6- ~
其中operator()被声明为模版函数以支持不同类型之间的赋值。 &G3$q,`H
然后我们就可以书写_1的类来返回assignment }UG<_bE|
(YYwn@NGj
'sk M$jr
;b_<5S
class holder Z_T~2t
{ ^vOEG;TR<-
public : ZalL}?E
?
template < typename T > J %E0Wd
assignment < T > operator = ( const T & t) const clIn}wQ
{ b}hQU~,E
return assignment < T > (t); 2D3mTpw
} Ka"1gbJ|
} ; iciRlx.$c
z qd1G(tO
HLE%f;
由于该类是一个空类,因此我们可以在其后放心大胆的写上: gM6o~ E
#vPk
XcP
static holder _1; grJ(z)c
Ok,现在一个最简单的lambda就完工了。你可以写 2k`Q+[?{q>
b1Ba}
for_each(v.begin(), v.end(), _1 = 1 ); ~BXy)IB6
而不用手动写一个函数对象。 ?.nD!S@
_Vr}ipx-k
H\|H]: CE
Jb8%A@Z+
四. 问题分析 Q:Y`^jP
虽然基本上一个Lambda已经初步实现出来了,但是仔细想想,问题也是很多的。 }<