文章目錄
- 關於C++0x
- 關於lambda運算式
- Ruby代碼
- C++代碼
關於C++0x預計於明年底推出的新標準C++0x,雖說已接近收官階段,卻仍有若干有待接納的新提案被提出。尤其值得關注的是,與lambda運算式以及局部函數相關的提案“Unified Function Syntax(統一的函數文法)”,儘管不受標準委員會待見(兩年間曆經四次延遲表決,兩次不予通過),仍然“頑強地”推出了其第7個版本N2989,提案作者鍥而不捨的精神實在令人欽佩。 關於lambda運算式受函數型編程風格的影響,一些OOP為主題思想的靜態語言紛紛推出了lambda這一以短小的匿名函數為特點的語言設施,典型的如微軟的VB9和C#3.0。與此相對應的是,眾多動態指令碼語言(python, ruby, javascript)則早就具備了相應的語言特性,Ruby的過程對象便是其中一例。這一次借C++0x新標準的東風,C++語言不甘人後同樣引入了這一激動人心的新特性,為函數型編程風格在C++語言內的進一步推廣打下了堅實的基礎。 以下用C++0x中的lambda運算式來類比Ruby的過程對象。 Ruby代碼class Array<br /> def inject(n)<br /> each { |value| n = yield(n, value) }<br /> n<br /> end<br /> def sum<br /> inject(0) { |n, value| n + value }<br /> end<br /> def product<br /> inject(1) { |n, value| n * value }<br /> end<br /> def find<br /> for i in 0...size<br /> value = self[i]<br /> return value if yield(value)<br /> end<br /> return nil<br /> end<br />end<br />[ 1, 2, 3, 4, 5 ].sum # 15<br />[ 1, 2, 3, 4, 5 ].product # 120<br />[ 1, 2, 3, 4, 5 ].find {|v| v*v > 10 } # 4<br />有關Ruby的過程對象以及這段Ruby代碼的說明,請參考Ruby語言中的泛回調及其在C++語言中的類比實現一文。 C++代碼#include <array><br />#include <functional><br />//#include <numeric><br />#include <algorithm><br />#include <boost/assign.hpp><br />#include <iostream></p><p>using namespace std;</p><p>template<typename T><br />struct Array : public vector<T><br />{<br />template<typename _Iter><br />Array(_Iter _First, _Iter _Last) : vector(_First, _Last) {}</p><p>T inject(T n, function<T(T,T)> f) const {<br />for_each(begin(), end(), [&](T value){n = f(n, value);});<br />return n;<br />//return accumulate(begin(), end(), n, f);<br />}<br />T sum() const {<br />return inject(0, [](T n, T value){return n + value;});<br />}<br />T product() const {<br />return inject(1, [](T n, T value){return n * value;});<br />}<br />const T* find(function<bool(T)> f) const {<br />auto i = find_if(begin(), end(), f);<br />return i == end() ? nullptr : &*i;<br />}<br />};</p><p>int main()<br />{<br />Array<int> a = boost::assign::list_of(1)(2)(3)(4)(5);<br />//Array<int> a = {1, 2, 3, 4, 5};<br />cout << a.sum() << endl;<br />cout << a.product() << endl;<br />cout << *a.find([](int v){return v * v > 10;}) << endl;</p><p>return 0;<br />}</p><p>//15<br />//120<br />//4C++代碼說明
- Ruby數組用標準庫的vector組件來類比。
- Ruby數組的初始化用boost庫的assign組件來類比。
註:Array類中若加入初始化列表構造器(C++0x新特性,VC10尚不支援),其初始化方式將可得到明顯改善(第36行)。
- Ruby過程對象用lambda運算式來類比。
- Ruby代碼中的each方法用標準庫的for_each演算法來類比。
- 如果不類比具體演算法,Ruby代碼中的inject方法也可用標準庫的accumulate演算法來實現。
具體做法為:注釋掉第17,18行,反注釋第3,19行。
- Ruby代碼中的find方法直接用標準庫的find_if演算法來實現(具體演算法不予類比)。
- 第28行的auto是C++0x新引入的關鍵字,用於自動類型推導,與C#3.0中的var相類似。
註:嚴格地說,是“舊瓶裝新酒”,auto關鍵字的原意(表示自動分配的局部變數類型,由於可省略而絕少被使用)在新標準中已經被廢除。
- 第29行的nullptr也是C++0x新引入的關鍵字,用於替代NULL表示null 指標。
- 原屬於Boost庫的模版類function在新標準中將正式進入標準庫。
function類型的變數不僅能存放函數指標和函數對象,也能存放lambda運算式。