- 下文中的仿函数是泛称,平时用于STL算法的判别式或判别式类的对象属于仿函数的一种特殊情况(即要求返回类型为bool)
- STL中的函数配接器,是指能够将仿函数和另一个仿函数或仿函数和某个值或仿函数和某一个一般函数结合起来形成一个新的仿函数
- 在STL中函数配接器一共有四个,分别是:bind1st,bind2nd,not1,not2
1.对于接受两个参数的仿函数op(param1, param2):
bind1nd(op ,value) //相当于构成op(value,param2),即用value覆盖掉op的第一个参数
bind2nd(op ,value) //相当于构成op(param1,value),即用value覆盖掉op的第二个参数
2…对于接受一个参数的仿函数op(param):
not1(op) //相当于构成!op(param),即op(param)的结果进行逻辑非运算
not2(op) //相当于构成!op(param,param),即把op(param,param)的结构进行逻辑非运算
- 注:
一、编写函数子类op时,必须继承自基类unary_function或binary_function, 分别对应op中的operator()函数的参数个数和返回值;
即operator()若接受一个参数,则继承unary_function,两个参数则继承binary_function,后面跟上operator()的返回类型;
class op : public binary_function<T1, T2, bool>{
bool operator()(T1 a, T2 b){
...
}
};
二、函数子类所继承的基类unary_function或binary_function是STL提供的模板,需要先指定模板参数,规则是:
- operator()的参数和返回类型中不含指针时,要省略const和&
class op : public binary_function<T1, T2, bool>{
bool operator()(const T1& a, const T2& b){
...
}
};
- 以指针为参数或返回类型,则把这个类型原样抄;
class op : public binary_function<const T1*, const T2*, bool>{
bool operator()(const T1* a, const T2* b){
...
}
};
三、对于普通函数f也需要用函数配接器结合时,需要先用ptr_fun(f)封装,使普通函数变为仿函数才能用于配接器;
//下面例子中的普通函数fun,需先ptr_fun(fun)变成仿函数,才能使用配接器bind2nd与value值1结合,得到一个新的仿函数bind2nd(ptr_fun(fun),1)
for_each(B.begin(), B.end(), bind2nd(ptr_fun(fun),1));
- 示例代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<iterator>
#include<functional>
using namespace std;
class A :public binary_function<int,int,void>
{
public:
A(){}
~A(){}
bool operator()( int a, int b) const
{
ostream_iterator<int> os(cout,"--");
*os = a + b;
}
private:
};
void fun(int a,int b)
{
ostream_iterator<int> os(cout,"--");
*os = a + b;
}
int Get(int a)
{
return a;
}
int main()
{
vector<int> B;
for(int i = 0;i<5;i++) B.push_back(i);
//bind2nd将一个仿函数和一个数值结合
for_each(B.begin(), B.end(), bind2nd(A(),2));
cout<<endl;
//先用ptr_fun把一个普通函数适配成一个仿函数,再用bind2nd将之与常数结合
for_each(B.begin(), B.end(), bind2nd(ptr_fun(fun),1));
cout<<endl;
//bind2nd将一个仿函数与普通函数结合
for_each(B.begin(), B.end(), bind2nd(A(),Get(3)));
}