posts - 18,  comments - 104,  trackbacks - 0

看看之前做到哪里了:实现了一个赋值的lambda表达式。

这次来看看怎么添加新的运算进去,然后再说点关于表达式的问题,为以后的扩展打下理论基础。

先看看之前的代码吧,

 1 template <typename _U>
 2 struct op
 3 {
 4     op(_U i)
 5         : _i(i)
 6     {}
 7 
 8     _U _i;
 9 
10     template<typename _T>
11     _T& operator()(_T& i)
12     {
13         i = _i;
14     }
15 };
16 
17 struct place_holder
18 {
19     template <typename _T>
20     op<_T> operator=(_T i)
21     {
22         return op<_T>(i)
23     }
24 };
25 
26 place_holder _1;
27 
28 vector<double> v;
29 for_each(v.begin(), v.end(), _1 = 3);

现在,要在这个基础上,添加新的操作进来,比如说operator+=吧。要怎么做呢?

1.  place_holder要重载operator+= 才可以,因为place_holder的主要任务就是替我们生成一个仿函数。
2.  要有相应的仿函数来真正的做 += ,也就是说在仿函数的operator()里面,要有真正干活的操作。

好了,开始吧, 先看看实现,然后在解释。

 1 struct op
 2 {
 3     op(int i)
 4         : _i(i)
 5     {}
 6 
 7     int _i;
 8 
 9     int operator()(int& i)
10     {
11         return i = _i;
12     }
13 };
14 
15 struct op1
16 {
17     op1(int i)
18         : _i(i)
19     {}
20 
21     int _i;
22 
23     int operator()(int& i)
24     {
25         return i += _i;
26     }
27 };
28 
29 struct place_holder
30 {
31     op operator=(int i)
32     {
33         return op(i);
34     }
35 
36     op1 operator+=(int i)
37     {
38         return op1(i);
39     }
40 };
41 
42 place_holder _1;
43 
44 void main()
45 {
46 
47     vector<int> v;
48     v.push_back(12);
49     v.push_back(1342);
50     v.push_back(23);
51 
52     for_each(v.begin(), v.end(), _1 += 3);
53 }

好了,现在+=操作已经被支持了。多么简单呀。来看看都做了些什么:

1.  给place_holder增加了一个operator+=函数, operator+= 返回op1类型的仿函数。
2.  增加了一个op1的仿函数(类模板),用来真正的执行 += 的运算。

当编译器看到  _1 += 3 时,去找到 place_holder::operator+=, 然后把模板参数推导成 int,返回一个 op1<int> 对象。
在for_each里面,就调用op1<int>::operator+=了。

当然也可以这么用:

1 double x = 0.0;
2 (_1 += 10.4)(x);

到这里大家想必已经可以照猫画虎,实现其他操作了吧。但是当实现的操作多起来的时候,新的问题就来了,比如想要个 _1 = _2 + 3.0 的时候呢?看看下面的代码:

 1 _1 = _2 + 3.0    //lambda表达式
 2 
 3 void fun(double& lhs, const double& rhs)  //相同功能函数
 4 {
 5     lhs = rhs + 3.0;
 6 }
 7 
 8 struct op
 9 {
10     template <typename _T>
11     _T operator(_T& lhs, const _T& rhs)
12     {
13         lhs = rhs + 3.0;
14     }
15 };
16 

看看lambda表达式为我们省了多少代码!当然我不是为了说这个而写这么长段代码,我想说,那个op是我们的最终目标,能实现吗?不能!因为在op里面直接出现了3.0,按照前面的惯例,应该在op里面有一个成员变量来保存3.0,不是吗?根本问题不在这里。

仔细想想我们到底在做什么,我们在用template的技法,“编译”表达式。
place_holder其实就像C++的表达式,op就像汇编语言,通过template技法,把place_holder的表达式“编译”成用op组成的操作,op是可以直接被C++运行的仿函数。也就是说是一个从lambda语法到C++语法的编译器,但是这个编译器靠template技法实现,由真正的C++编译器进行模板推导,最后“编译”成C++的仿函数。所以一句话就是:

用template技法实现的从lambda语法到C++语法的“编译器”。

所以根本问题在于op的这种写法没有办法扩展,难道对于每种连起来的操作,都分别写一个op吗(比如_1 = (_2 + 3.0) * (_2 - 3.0),C++中表达式无数,要是每种都要写个op,那要lambda何用 )?op相当于汇编,只要几个简单的运算就OK,关键在于按照place_holder的表达,把op组合起来。

下一篇准备介绍一下boost::tuple,和表达式编译,因为它们是实现lambda的关键武器。
posted on 2009-02-22 22:11 尹东斐 阅读(1758) 评论(1)  编辑 收藏 引用 所属分类: 深入探索 boost::lambda 系列

FeedBack:
# re: 深入探索 boost::lambda 系列(三)
2011-06-16 17:48 | lucida
lambda里面想构造一个class A的实例,A带构造参数的,怎么写  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


<2009年3月>
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

留言簿(4)

随笔档案

文章分类

文章档案

相册

好友博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜