一。標准庫定義的函數對象:
標准庫定義了一組用於算術、關系、邏輯運算的函數對象類,他們都是類模板,定義在頭文件functional中;
1. 在這裡舉一個算術函數對象類型的例子:plus<Type> 對2個給定元素進行 + 運算,它定義了調用操作符的類模板,所以是二元函數對象;
要對數值1和2進行加法運算,可以寫如下代碼:
plus<int> add; //定義加法運算的類模板的實例;
int sum = add(1, 2); //調用了類模板plus定義的調用操作符函數;
C++適配器概括 http://www.linuxidc.com/Linux/2014-03/98198.htm
C++中函數指針和函數對象的區別與聯系 http://www.linuxidc.com/Linux/2014-02/96920.htm
2. 將標准庫函數對象應用於算法,用到二元函數對象greater<Type>,返回真假值,如果第一個參數大於第二個參數,返回真值,否則返回假值;
例如,對vector 中的元素從大到小排序:
int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
vector<int> ivec(a, a+8);
sort(ivec.begin(), ivec.end(), greater<int>()); //算法sort的第三個實參為一個臨時對象,由類模板greator<Type>實例化,並調用默認構造函數生成臨時對象,算法sort使用該臨時對象的調用操作符比較元素;
二元函數對象返回的真假值,是第一個參數相對於第二個參數的結果,即第一個參數小於,等於,或大於第二參數,則返回真值;
二。函數適配器:
對於上述例子,如果在vector中查找大於5的所有元素,我們可以使用算法find_if,但是find_if的第三個參數為一個接受一個形參的函數,而且find_if只傳遞一個實參到函數對象,但是函數對象greator<Type>是二元函數對象,接受兩個形參,並且還要和被查找的值5進行比較,所以以下寫法是錯誤的:
find_if(ivec.begin(), ivec.end(), greater<int>());
現在遇到的問題就是如何將接受兩個形參的函數對象轉換為接受一個形參的函數對象,以及如何指定被比較的數值5,於是函數適配器產生了:
函數適配器就是通過將一個操作數綁定到給定值而將二元函數對象轉換為一元函數對象,函數適配器分為兩類:綁定器 與 求反器;
1. 綁定器:bind1st:將給定值綁定到二元函數對象的第一個實參; bind2nd:將給定值綁定到二元函數對象的第二個實參;他們的返回值都是一元函數對象;
此例中,可以將數值5綁定到二元函數對象greater<Type>的第二個實參,那麼greater<Type>的第一個實參就由find_if算法函數提供,因此使用bind2nd適配器;
vector<int>::iterator ite = ivec.begin();
while((ite = find_if(ite, ivec.end(), bind2nd(greater<int>(), 5))) != ivec.end())
{
cout << *ite << " ";
ite++;
}
bind2nd返回一個一元函數對象,根據greater<int>的實參類型進行實參模板推斷,在這裡推斷出的模板實參是int類型,根據構造函數greater<int>()生成的greater函數對象,返回一個帶有兩個實參返回類型為bool型的函數對象,第一個實參是vector元素的類型,第二個就是被比較的數值5,形式類似 boo fun(int val, 5),然後就可以用該一元函數對象對每個元素同數值5進行比較了;
此例也可以使用適配器 bind1st 與 函數對象less<Type>進行組合,即將5綁定到 less 的第一個操作數,第二個參數就是算法函數傳進的元素,less<Type>用於比較第一個值是否小於第二個值;
2. 求反器:not1:對一元函數對象的結果取反; not2:對二元函數對象的結果取反;
//如下語句功能是統計小於等於5的元素個數,用到了表示 <= 的函數對象less_equal<Type>;
size_t n1 = count_if(ivec.begin(), ivec.end(), bind2nd(less_equal<int>(), 5));
如果改為統計不小於等於5的元素個數,修改語句如下:
size_t n1 = count_if(ivec.begin(), ivec.end(), not1(bind2nd(less_equal<int>(), 5)));
因為bind2nd返回的是一元函數對象,所以使用not1,而不是not2;
全部代碼:
#include <functional>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
vector<int> ivec(a, a+8);
size_t n1 = count_if(ivec.begin(), ivec.end(), bind2nd(less_equal<int>(), 5));
cout << "n1:" << n1 << endl;
//size_t n = count_if(ivec.begin(), ivec.end(), not1(bind2nd(less_equal<int>(), 5)));
size_t n2 = count_if(ivec.begin(), ivec.end(), bind1st(less_equal<int>(), 5));
cout << "n2:" << n2 << endl;
less_equal<int> le;
size_t n3 = le(5, 8);
cout << "n3:" << n3 << endl;
vector<int>::iterator ite = ivec.begin();
while((ite = find_if(ite, ivec.end(), bind2nd(greater<int>(), 5))) != ivec.end())
{
cout << *ite << " ";
ite++;
}
cout << endl;
sort(ivec.begin(), ivec.end(), greater<int>());
while(ite != ivec.end())
{
cout << *ite << " ";
ite++;
}
cout << endl;
}
運行結果:
n1:5
n2:4
n3:1
6 7 8