C++ 11在語言中加入了lambda表達式,lambda表達式可以友善地構造匿名函數。當我們定義lambda表達式時,C++編譯器會建立一個匿名的與lambda表達式有關的類類型。
使用lambda表達式進行函數式程式設計
我們知道,在函數式程式設計語言中,比如
scheme
,函數作為一等公民,與普通的資料類型相同,可以作為函數的參數以及傳回值,可以很友善的實作高階函數等。 在C++中,我們可以借助于函數對象以及函數指針實作。 在C++ 11中,借助于lambda表達式,也可以實作高階函數。
将lambda表達式用作傳回值
定義在頭檔案中的std::function是多态的函數對象包裝,類似函數指針。它可以綁定至任何可以被調用的對象(仿函數、成員函數指針、函數指針和lambda表達式),隻要參數和傳回類型符合包裝的類型即可。傳回一個double、接受兩個整數參數的函數包裝定義如下:
function< double(int, int) > my_wrapper;
通過std::function,可以從函數中傳回lambda表達式,示例如下:
function<int(void)> multiplyBy2Lambda(int x)
{
return [=]()->int{ return 2 * x; };
}
這個函數的主體部分建立了一個lambda表達式,這個lambda表達式通過值捕捉所在作用域的變量,并傳回一個整數,這個傳回的整數是傳給multiplyBy2Lambda()的值的兩倍。這個multiplyBy2Lambda()函數的傳回值類型為 function
将lambda表達式用作參數
可以編寫lambda表達式作為參數的函數。例如,可通過這種方式實作回調函數。下面的代碼實作了一個testCallback()函數,這個函數接受一個整數vector和一個回調函數作為參數。這個實作疊代給定vector中的所有元素,并對每個元素調用回調函數,回調函數接受vector中每個元素作為int參數,并傳回一個布爾值。如果回調函數傳回false,那麼停止疊代。
//注意參數類型,第二個參數如果使用pass by reference,則必須加const修飾,否則編譯錯誤
//如果采用值傳遞,無影響
void testCallback(const vector<int>& vec, const function<bool(int)>& callback)
{
for (auto i : vec)
{
if (!callback(i))
break;
cout << i << " ";
}
cout << endl;
}
測試:
auto callback = []( int i ) -> bool { return i < 6; };
vector<int> vec( 10 );
int index = 0;
generate( vec.begin(), vec.end(), [&index] {return ++index; } );
testCallback( vec, callback );
結果:
lambda表達式實作高階函數
有關C++高階函數可以參看我的博文:C++高階函數
int sumInt( int a, int b ){
int result { 0 };
for ( int i = a; i <= b; ++i ) {
result += i;
}
return result;
}
int sumCube( int a, int b ){
int result { 0 };
for ( int i = a; i <= b; ++i ) {
result += i * i * i;
}
return result;
}
//advanced abstraction
template < class T >
T sumGeneric( T a, T b, const function< int( int ) >& func, const function< void( int& ) >& next ){
T result( 0 );
for ( T i = a; i <= b; next( i ) ) {
result += func( i );
}
return result;
}
上述示例中,前兩個求和函數有着相同的邏輯,可以進行抽象 sumGeneric
。
測試:
auto self = []( int i ) -> int { return i; };
auto inc = []( int& i ) -> void { ++i; };
auto cube = []( int i ) -> int { return i * i * i; };
cout << "Normal Cal:" << endl;
cout << "sumInt( 1, 50 ):" << sumInt( 1, 50 ) << " sumCube( 1, 50 ):" << sumCube( 1, 50 );
cout << endl << "High Order Function:" << endl;
cout << "sumInt( 1, 50 ):" << sumGeneric( 1, 50, self, inc )
<< " sumCube( 1, 50 ):" << sumGeneric( 1, 50, cube, inc );
結果:
代碼下載下傳位址:
https://github.com/bjut-hz/High-Order-Function