刚注册好cppblog的用户,这算是处女作了。 最近在学习boost::lambda, 分享下学习心得,共同进步。
当然这篇不是讲boost::lambda的用法的,如有有人感兴趣,可以参照:http://www.boost.org/doc/libs/1_38_0/doc/html/lambda.html
boost::lambda很复杂,一两句话也说不清楚,我尽力描述的简单一点,慢慢增加难度。
对我来说,boost::lambda省了不少事,我是喜欢stl algorithm的,现在基本上除非特殊情况,程序里面都不出现循环了。用for_each, transform 等等都可以搞定,否则,就要考虑数据结构和算法是不是有问题了。
但是问题在于每次用for_each的时候,都要定义一个仿函数(Modern C++ Design 这么叫的),麻烦,程序看起来也不怎么优雅顺畅,总要停下来去看那个仿函数到底干什么了,写的时候还要想是不是要泛化,很头痛。有了boost::lambda,就爽多了。看起来一目了然,写起来简单明了,不用关心类型。(是不是搞推销的?)
言归正传吧。
比如下面这段代码:
1 vector<int> v;
2 v.push_back(12);
3 v.push_back(1342);
4 v.push_back(23);
5
6 struct OP
7 {
8 void operator()(int &i)
9 {
10 i = 3;
11 }
12 };
13
14 for_each(v.begin(), v.end(), OP());
够简单吧,把整个容器的值都改成3. 看到那个OP了吧,很简单的一件事情,非要让人写这么个struct,要是写成class,还要public,更郁闷。
看看用了boost::lambda以后的效果吧。
1 vector<int> v;
2 v.push_back(12);
3 v.push_back(1342);
4 v.push_back(23);
5
6 for_each(v.begin(), v.end(), _1 = 3);
7
比不用lambda整整少了一个OP定义呀,因为 string("OP()").length() == string("_1=3").length() .
那么,怎么才能达到这个效果呢,在这里,先假设我们只用int类型,关于泛化,下一篇再说,一次吃多了消化不良的。
熟悉for_each的都知道,for_each的第3个参数是个函数对象(我不用指针抱歉),注意区分仿函数和函数对象,仿函数是个类型,函数对象是个对象。
那么也就是说 _1 = 3 的结果应该是个函数对象,而且是个一元函数对象(不了解的去看for_each实现)。知道了这个,很容易写个大概:
1 struct op
2 {
3 ??? operator()(int& i)
4 {
5 i = ???;
6 }
7 };
8
9 struct place_holder
10 {
11 op operator=(int i)
12 {
13 return op???;
14 }
15 };
16
17 place_holder _1;
18
19 for_each(v.begin(), v.end(), _1 = 3);
???不是乱码,这里只是暂时不知道写什么。
我说过,这篇里面类型都是int,但是那个3怎么处理呢,明显要保存的仿函数里面去么,所以上面的代码进一步修改,
个OP里面增加变量,来保存3,函数返回值现在不重要,就写成int吧,以后有问题再说。
于是代码变成:
1 struct op
2 {
3 op(int i)
4 : _i(i)
5 {}
6
7 int _i;
8
9 int operator()(int& i)
10 {
11 i = _i;
12 }
13 };
14
15 struct place_holder
16 {
17 op operator=(int i)
18 {
19 return op(i)
20 }
21 };
22
23 place_holder _1;
24
25 for_each(v.begin(), v.end(), _1 = 3);
问题解决。
看到这里,整个程序已经可以执行了。把容器的值改成3,没问题吧。
整片文章都在一个假设之下,就是只用int,那要是不用int呢,情况就复杂一点了,下篇再讨论。 如果熟悉template的话,下篇很容易,否则,复习咯。
posted on 2009-02-19 19:19
尹东斐 阅读(1286)
评论(0) 编辑 收藏 引用 所属分类:
深入探索 boost::lambda 系列