看看之前做到哪里了:實(shí)現(xiàn)了一個(gè)賦值的lambda表達(dá)式。
這次來(lái)看看怎么添加新的運(yùn)算進(jìn)去,然后再說(shuō)點(diǎn)關(guān)于表達(dá)式的問(wèn)題,為以后的擴(kuò)展打下理論基礎(chǔ)。
先看看之前的代碼吧,
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);
現(xiàn)在,要在這個(gè)基礎(chǔ)上,添加新的操作進(jìn)來(lái),比如說(shuō)operator+=吧。要怎么做呢?
1. place_holder要重載operator+= 才可以,因?yàn)閜lace_holder的主要任務(wù)就是替我們生成一個(gè)仿函數(shù)。
2. 要有相應(yīng)的仿函數(shù)來(lái)真正的做 += ,也就是說(shuō)在仿函數(shù)的operator()里面,要有真正干活的操作。
好了,開(kāi)始吧, 先看看實(shí)現(xiàn),然后在解釋。
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 }
好了,現(xiàn)在+=操作已經(jīng)被支持了。多么簡(jiǎn)單呀。來(lái)看看都做了些什么:
1. 給place_holder增加了一個(gè)operator+=函數(shù), operator+= 返回op1類型的仿函數(shù)。
2. 增加了一個(gè)op1的仿函數(shù)(類模板),用來(lái)真正的執(zhí)行 += 的運(yùn)算。
當(dāng)編譯器看到 _1 += 3 時(shí),去找到 place_holder::operator+=, 然后把模板參數(shù)推導(dǎo)成 int,返回一個(gè) op1<int> 對(duì)象。
在for_each里面,就調(diào)用op1<int>::operator+=了。
當(dāng)然也可以這么用:
1 double x = 0.0;
2 (_1 += 10.4)(x);
到這里大家想必已經(jīng)可以照貓畫虎,實(shí)現(xiàn)其他操作了吧。但是當(dāng)實(shí)現(xiàn)的操作多起來(lái)的時(shí)候,新的問(wèn)題就來(lái)了,比如想要個(gè) _1 = _2 + 3.0 的時(shí)候呢?看看下面的代碼:
1 _1 = _2 + 3.0 //lambda表達(dá)式
2
3 void fun(double& lhs, const double& rhs) //相同功能函數(shù)
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表達(dá)式為我們省了多少代碼!當(dāng)然我不是為了說(shuō)這個(gè)而寫這么長(zhǎng)段代碼,我想說(shuō),那個(gè)op是我們的最終目標(biāo),能實(shí)現(xiàn)嗎?不能!因?yàn)樵趏p里面直接出現(xiàn)了3.0,按照前面的慣例,應(yīng)該在op里面有一個(gè)成員變量來(lái)保存3.0,不是嗎?根本問(wèn)題不在這里。
仔細(xì)想想我們到底在做什么,
我們?cè)谟胻emplate的技法,“編譯”表達(dá)式。
place_holder其實(shí)就像C++的表達(dá)式,op就像匯編語(yǔ)言,通過(guò)template技法,把place_holder的表達(dá)式“編譯”成用op組成的操作,op是可以直接被C++運(yùn)行的仿函數(shù)。也就是說(shuō)是一個(gè)從lambda語(yǔ)法到C++語(yǔ)法的編譯器,但是這個(gè)編譯器靠template技法實(shí)現(xiàn),由真正的C++編譯器進(jìn)行模板推導(dǎo),最后“編譯”成C++的仿函數(shù)。所以一句話就是:
用template技法實(shí)現(xiàn)的從lambda語(yǔ)法到C++語(yǔ)法的“編譯器”。
所以根本問(wèn)題在于op的這種寫法沒(méi)有辦法擴(kuò)展,難道對(duì)于每種連起來(lái)的操作,都分別寫一個(gè)op嗎(比如_1 = (_2 + 3.0) * (_2 - 3.0),C++中表達(dá)式無(wú)數(shù),要是每種都要寫個(gè)op,那要lambda何用 )?op相當(dāng)于匯編,只要幾個(gè)簡(jiǎn)單的運(yùn)算就OK,關(guān)鍵在于按照place_holder的表達(dá),把op組合起來(lái)。
下一篇準(zhǔn)備介紹一下boost::tuple,和表達(dá)式編譯,因?yàn)樗鼈兪菍?shí)現(xiàn)lambda的關(guān)鍵武器。
posted on 2009-02-22 22:11
尹東斐 閱讀(1791)
評(píng)論(1) 編輯 收藏 引用 所屬分類:
深入探索 boost::lambda 系列