概念
所谓的“函数配接器”是指能够将仿函数和另一个仿函数(或者某个值,或者另一个仿函数)结合起来的仿函数。函数配接器也声明与<functional>中。
通过函数配接器,我们可以把多个仿函数结合起来,形成强大的表达式,这种编程方式叫做functional composition(功能复合、函数复合)。
STL中预定义了四种类型的函数配接器,如图表1,函数配接器使用效果见例子1.
例子1
/**************************************************************** *函数名称:FuncAdapter *功 能:预定义的函数配接器举例 *作 者:Jin *日 期:2016年6月7日 ****************************************************************/ void FuncAdapter() { typedef vector<int> IntVector; IntVector Container; Container.push_back(10); Container.push_back(15); Container.push_back(20); Container.push_back(9); cout << "element in the container is: "; copy(Container.begin(), Container.end(), ostream_iterator<int>(cout, " ")); cout << endl; //bind2nd范式: param > 15 //output:1个 int nNumber1 = count_if(Container.begin(), Container.end(), bind2nd(greater<int>(), 15)); cout << "The number of elements in Container greater than 15 is: " << nNumber1 << endl; //bind1st范式: 15 > param int nNumber2 = count_if(Container.begin(), Container.end(), bind1st(greater<int>(), 15)); cout << "The number of elements in Container less than 15 is: " << nNumber2 << endl; // not1 bind1st范式: !(param > 15) == (param <= 15) int nNumber3 = count_if(Container.begin(), Container.end(), not1(bind2nd(greater<int>(), 15))); cout << "The number of elements in Container less than or equal to 15 is: " << nNumber3 << endl; sort(Container.begin(),Container.end(),less<int>()); PrintElements(Container, "descending: "); //not2 范式 !op(param1, param2) sort(Container.begin(),Container.end(),not2(less<int>())); PrintElements(Container, "Ascending: "); }
运行结果:
成员函数配接器
为了能够将类别中的成员函数和仿函数结合起来,需要是使用成员函数配接器,将成员函数转变仿函数,STL中预定义了两种成员函数配接器接口见表2.
成员函数配接代码见例子2.
例子2
class Person { public: //member function void Print() const { cout << m_strName << endl; } //member function void PrintWithPrefix(string strPrefix) const { std::cout << strPrefix << m_strName << endl; } //construction function Person(string strName):m_strName(strName){} private: string m_strName; }; /**************************************************************** *函数名称:MemberFunction *功 能:针对成员函数设计的函数配接器 *作 者:Jin *日 期:2016年6月8日 ****************************************************************/ void MemberFuncAdapter() { vector<Person> PersonVector; //vector中是对象 vector<Person*> PtrPersonVector; //指针序列 const int nMaxPerson = 5; string strNames[nMaxPerson] = { "David", "Kangkang", "Hua", "Mike", "Lily" }; for (int i = 0; i < nMaxPerson; i++) { Person per(strNames[i]);; PersonVector.push_back(per); Person *PtrPer = new Person(strNames[i]); PtrPersonVector.push_back(PtrPer); } //it is object in the vector: call print member function for_each(PersonVector.begin(), PersonVector.end(), mem_fun_ref(&Person::Print)); //it is object in the vector: call PrintWithPrefix member function for_each(PersonVector.begin(), PersonVector.end(), bind2nd(mem_fun_ref(&Person::PrintWithPrefix), "person:")); cout << endl << "ptr object: " << endl; //it is ptr in the vector: call print member function for_each(PtrPersonVector.begin(), PtrPersonVector.end(), mem_fun(&Person::Print)); //it is ptr in the vector: call PrintWithPrefix member function for_each(PtrPersonVector.begin(), PtrPersonVector.end(), bind2nd(mem_fun(&Person::PrintWithPrefix), "PersonName:")); //删除申请的空间 for (unsigned i = 0; i < PtrPersonVector.size(); i++) { delete PtrPersonVector[i]; } }运行效果:
一般函数配接器
针对非成员函数而设计的函数配接器是ptr_fun见表3,从而可以和仿函数结合起来。具体代码使用见例子3。
例子3
/**************************************************************** *函数名称:CommonFuncAdapter *功 能:用于一般函数身上的函数配接器 *作 者:Jin *日 期:2016年6月14日 ****************************************************************/ void CommonFuncAdapter() { vector <char*> v1; vector <char*>::iterator Iter1, RIter; v1.push_back ("Open"); v1.push_back ("up"); v1.push_back ("the"); v1.push_back ("pearly"); v1.push_back ("gates"); cout << "Original sequence contains: " ; for (Iter1 = v1.begin(); Iter1 != v1.end(); Iter1++) { cout << *Iter1 << " "; } cout << endl; // To search the sequence for "pearly" // use a pointer_to_function conversion RIter = find_if(v1.begin(), v1.end(), not1(bind2nd(ptr_fun(strcmp), "pearly"))); if (RIter != v1.end()) { cout << "The search for 'pearly' was successful. "; cout << "The next character string is: " << *++RIter << "." << endl; } }
运行结果:
自定义仿函数的可配接性
在某些情况下,我们需要编写自己的仿函数,但是希望它们能够和函数配接器搭配运用,就必须满足某些条件:
提供一些成员函数来反映其参数和返回值的型别,STL提供了如下的数据结构:
// TEMPLATE STRUCT unary_function template<class _Arg, class _Result> struct unary_function { // base class for unary functions typedef _Arg argument_type; typedef _Result result_type; }; // TEMPLATE STRUCT binary_function template<class _Arg1, class _Arg2, class _Result> struct binary_function { // base class for binary functions typedef _Arg1 first_argument_type; typedef _Arg2 second_argument_type; typedef _Result result_type; };仿函数上述两种形式之一,就能轻松满是“可配接”的条件,例如预定义仿函数great,less都继承了上述结构,具体“可配接”性的分析后文再单独分享。
template<class _Ty> struct less: 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); } }; template<class _Ty> struct negate : public unary_function<_Ty, _Ty> { // functor for unary operator- Ty operator()(const _Ty& _Left) const { // apply operator- to operand return (-_Left); } };