概念
所谓的“函数配接器”是指能够将仿函数和另一个仿函数(或者某个值,或者另一个仿函数)结合起来的仿函数。函数配接器也声明与<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.\n";
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);
}
};