STL函數適配器
阿新 • • 發佈:2019-04-30
成員 begin void operator 綁定 定義 img 計算 轉換
一:適配器簡介
C++中有三類適配器,分別是容器適配器,叠代器適配器和函數適配器,這裏主要介紹函數適配器。
(一)函數適配器簡介
STL中已經定義了大量的函數對象,但是有時候需要對函數返回值進行進一步的簡單計算,或者填上多余的參數,
才可以帶入其他的算法中進行下一步數據處理,不能直接帶入算法。
函數適配器就實現了這一功能:將一種函數對象轉化為另外一種符合要求的函數對象。
函數適配器可以分為4大類:
綁定適配器(bind adaptor),
組合適配器(composite adaptor),
指針函數適配器(pointer adaptor),
成員函數適配器(member function adaptor)
(二)綁定適配器(bind adaptor)
(三)組合適配器(composite adaptor)
(四) 指針函數適配器(pointer adaptor)
(五)成員函數適配器(member function adaptor)
二:函數適配器輔助函數
直接構造STL中的函數適配器通常會導致冗長的類型聲明。---->之前說過模板函數和STL中類型是嚴格定義的,需要我們顯式寫出
為了簡化函數適配器的構造,
STL還提供了函數適配器輔助函數,借助於泛型自動推斷技術,無需顯式的類型聲明便可以實現函數適配器的構造。
三:常用函數適配器
標準庫提供一組函數適配器,用來特殊化或者擴展一元和二元函數對象。
(一)綁定器(binder): 將二元函數對象轉一元函數對象
binder通過把二元函數對象的一個實參綁定到一個特殊的值上,將其轉換成一元函數對象。
C++標準庫提供兩種預定義的binder適配器(適配器輔助函數):
bind1st和bind2nd,前者把值綁定到二元函數對象的第一個實參上,後者綁定在第二個實參上。
(二)取反器(negator) : 操作謂詞函數
negator是一個將函數對象的值翻轉的函數適配器。
標準庫提供兩個預定義的ngeator適配器(適配器輔助函數):
not1翻轉一元預定義函數對象的真值,而not2翻轉二元謂詞函數的真值。
(三)常用函數適配器案例:《重點》
1.使用綁定器和預定義函數對象
#include <iostream> #include <vector> #include <algorithm> #include <functional> //由於要使用到預定義函數對象,所以引入 using namespace std; template<typename T> void ShowEle(const T& t) //用於打印容器數據 { cout << t << " "; }
int main() { vector<int> v1, v2, v3; for (int i = 0; i < 10;i++) v1.push_back(rand() % 30); //v1數據插入 //打印數據 for_each(v1.begin(), v1.end(), ShowEle<int>); cout << endl; int num = count_if(v1.begin(), v1.end(), bind2nd(greater<int>(), 2)); cout << num << endl; system("pause"); return 0; }
補充:count和count_if
1)count(first,last,value):first是容器的首叠代器,last是容器的末叠代器,value是詢問的元素,整個函數返回int型。count函數的功能是:統計容器中等於value元素的個數。 2)count_if(first,last,comp) (在comp為true的情況下計數) 或者 count_if(first,last,value,comp) (這個是在comp為true的情況下統計容器中等於value的元素):first為首叠代器,last為末叠代器,value為要查詢的元素,comp為比較bool函數,為true則計數,函數返回型是int。 註:此兩個函數復雜度是線性的,適用於小規模運算。count_if更加靈活
2.使用自定義謂詞和綁定器《重點》
template<typename T> void ShowEle(const T& t) //用於打印容器數據 { cout << t << " "; } template<typename T> class Mygreater :public binary_function<T, T, bool> //1.自定義謂詞需要繼承binary_function { public: bool operator() (const T& iLeft, const T& iRight) const //2.重載()函數需要加上const,變為常函數 { return (iLeft > iRight);//如果是實現less<int>的話,這邊是寫return (iLeft<iRight); } }; int main() { vector<int> v1, v2, v3; for (int i = 0; i < 10;i++) v1.push_back(rand() % 30); //v1數據插入 //打印數據 for_each(v1.begin(), v1.end(), ShowEle<int>); cout << endl; int num = count_if(v1.begin(), v1.end(), bind2nd(Mygreater<int>(), 2)); cout << num << endl; system("pause"); return 0; }
template<class _Ty = void> struct greater : public binary_function<_Ty, _Ty, bool> { // functor for operator> bool operator()(const _Ty& _Left, const _Ty& _Right) const { // apply operator> to operands return (_Left > _Right); } };參照預定義函數greater
3.使用自定義二元函數對象和綁定器《重點》
template<typename T> void ShowEle(const T& t) //用於打印容器數據 { cout << t << " "; } //自定義二元函數對象---數據相加 template<typename T> class MySumAdd :public binary_function<T, T, int> { public: int operator()(const T& t1, const T& t2) const { return t1 + t2; } }; int main() { vector<int> v1, v2, v3; for (int i = 0; i < 10;i++) v1.push_back(rand() % 30); //v1數據插入 //打印數據 for_each(v1.begin(), v1.end(), ShowEle<int>); cout << endl; v2.resize(10); //將v1中所有數據加2 transform(v1.begin(), v1.end(), v2.begin(), bind2nd(MySumAdd<int>(), 2)); //打印數據 for_each(v2.begin(), v2.end(), ShowEle<int>); cout << endl; system("pause"); return 0; }
總之:自定義的仿函數和函數配接器搭配使用時,要繼承自template <...> unary_function or template <...> binary_function
unary_function可以作為一個一元函數對象的基類,他定義了兩個模板參數,分別是函數參數類型argument_type和返回值類型result_type,本身並不重載函數符(),由派生類去完成()操作符的重載工作。
binary_function可以作為一個二元函數對象的基類,他定義了三個模板參數,兩個函數參數類型first_argument_type和second_argument_type,以及返回值類型result_type,本身並不重載函數符(),由派生類去完成()操作符的重載工作
STL函數適配器