分类:
stl
2012-11-30 10:13
58人阅读
收藏
举报
转至:http://kymcuc.blog.163.com/blog/static/201942114201249105211285/
1、基本概念
所谓仿函数是一个定义了operator()的对象。虽然定义形式显然更为复杂,却有三大妙处
(1)仿函数比一般函数更灵巧。因为它可以拥有状态。事实上对于仿函数,可以同时拥有两个状态不同的实体
(2)每个仿函数都有其型别。因此可以将仿函数的型别当做template参数来传递。从而指定某种行为模式。此外还有一个好处:容器也会因为仿函数的不同而不同。
(3)执行速度上,仿函数通常比函数指针更快。
2.、仿函数可当做排序准则
要将某些类对象已已序形式置于容器中,则需要排序准则来排序,这个准则可以通过在类中重载operator<或定义一个函数来定义。
3、拥有内部状态的仿函数
#include<iostream> #include<list> #include<iterator> #include<algorithm> using namespace std; class is{ private: int value; public: is(int i):value(i){} int operator()(){return value++;} //仿函数的第二个括号里面是参数,实参是容器内的元素 }; int main() { list<int> coll; is seq(1); ::generate_n<::back_insert_iterator<list<int>>,int,is&>//指定各个参数类型,其中第三个参数指定为引用,因而会保持状态的改变 (::back_inserter(coll),4,seq); ::generate_n(::back_inserter(coll),4,is(42));//表示将从42开始的4个值复制到coll中,这个默认是值传递 ::generate_n(::back_inserter(coll),4,seq);//由于在第一次时,状态保存所以从五开始 for(list<int>::iterator i=coll.begin();i!=coll.end();++i) cout<<*i<<" "; cout<<endl; }
4、for_each的返回值
其返回值是其仿函数,这样就可以通过for_each的返回值来获取仿函数的状态
#include<iostream> #include<vector> #include<algorithm> #include<iterator> #include<memory> using namespace std; class mean{ private: long num; long sum; public: mean():num(0),sum(0){} void operator()(int elem){ num++; sum+=elem; } double value(){ return static_cast<double>(sum)/static_cast<double>(num); } };
int main() { vector<int> coll; for(int i=1;i<7;i++) coll.push_back(i); mean v=for_each(coll.begin(),coll.end(),mean()); cout<<v.value()<<endl; }
由于内部实现等原因,不应该传递一个行为取决于被拷贝次数或被调用次数的仿函数。
5、预定义的仿函数
这些函数包含在头文件< functional >,这些函数包括基本算术运算和基本的逻辑运算
6、函数配接器
表达式 |
效果 |
bind1st(op,value) |
op(value,param) |
bind2nd(op,value) |
op(param,value) |
not1(op) |
!op(param) |
not2(op) |
!op(param1,param2) |
#include<iostream> #include<vector> #include<functional> #include<algorithm> using namespace std; int main() { vector<int> coll; for(int i=1;i<=7;i++) coll.push_back(i); vector<int>::iterator iter; iter=::find_if(coll.begin(),coll.end(),::not1(::bind2nd(::modulus<int>(),2))); //对于所有奇数值,::bind2nd(::modulus<int>(),2)返回1,所以这个表达式用来找出第一个 //奇数值,对其取反表示找到第一个偶数值 cout<<*iter<<endl; }
7、针对成员函数而设计的函数配接器
表达式 |
效果 |
mem_fun_ref(op) |
调用op,那是某对象的一个const成员函数 |
mem_fun(op) |
调用op,那是某对象指针的一个const成员函数 |
#include<iostream> #include<functional> #include<vector> #include<algorithm> #include<string> using namespace std; class p{ private: string name; public: p(string n):name(n){} void print()const{cout<<name.c_str()<<endl;} void printw(string pre){cout<<pre.c_str()<<": "<<name.c_str()<<endl;} }; int main() { vector<p> coll;//对象调用mem_fun_ref vector<p*> coll1;//对象指针调用mem_fun coll.push_back(p("keyaming")); ::for_each(coll.begin(),coll.end(),::mem_fun_ref(&p::print)); p men("sg"); p* pmem=&men; coll1.push_back(pmem); ::for_each(coll1.begin(),coll1.end(),bind2nd(::mem_fun(&p::printw),"girl")); }
8、针对一般函数(非成员函数)而设计的函数配接器
表达式 |
效果 |
ptr_fun(op) |
op(param) |
|
op(param1,param2) |
#include<iostream> #include<vector> #include<functional> #include<algorithm> using namespace std; bool check(int elem) { return elem!=3; }
int main() { vector<int> coll; for(int i=0;i<7;++i) coll.push_back(i); vector<int>::iterator pos; pos=::find_if(coll.begin(),coll.end(),not1(ptr_fun(check))); cout<<*pos<<endl; }
9、让自定义的仿函数也可以使用函数配接器
可以编写自己的仿函数,但如果希望它们能够和函数配接器搭配使用,就必须满足某些条件,必须提供一些型别成员来反映其参数和返回值的型别。标准库提供了一些结构,仿函数只有继承这些结构就可以满足可配接的条件
template<class arg,class result> struct unary_funtion{ typedef arg argument_type; typedef result result_type; } template<class arg1,class arg2,class result> struct binary_function{ tyepdef arg1 first_argument_type; typedef arg2,second_argument_type; typedef result result_type; }
#include<iostream> #include<functional> #include<algorithm> #include<iterator> #include<vector> #include<cmath> using namespace std;
template<class t1,class t2> struct fopow:public std::binary_function<t1,t2,t1> //继承之后即可使用配接器 { t1 operator()(t1 base,t2 exp)const { return pow(base,exp); } };
int main() { vector<int> coll; for(int i=0;i<7;++i) coll.push_back(i); ::transform(coll.begin(),coll.end(),::ostream_iterator<int>(cout," "),::bind2nd(fopow<float,int>(),2)); cout<<endl; }
10、辅助用仿函数
功能 |
采用名称 |
f(g(elem)) |
compose_f_gx |
f(g(elem1,elem2)) |
|
f(g(elem),h(elem)) |
compose_f_gx_hx |
f(g(elem1),h(elem2)) |
compose_f_gx_hy |
compose.h #pragma #include<functional> namespace compose{ template<class OP1,class OP2> class compose_f_gx_t:public std::unary_function<typename OP2::argument_type,typename OP1::result_type> { private: OP1 op1; OP2 op2; public: compose_f_gx_t(const OP1&o1,const OP2&o2):op1(o1),op2(o2){} typename OP1::result_type operator()(const typename OP2::argument_type&x)const{ return op1(op2(x)); } };
template<class OP1,class OP2> inline compose_f_gx_t<OP1,OP2> compose_f_gx(const OP1&o1,const OP2&o2){ return compose_f_gx_t<OP1,OP2>(o1,o2); } }
namespace compose{ template<class OP1,class OP2,class OP3> class compose_f_gx_hx_t:public std::unary_function<typename OP2::argument_type,typename OP1::result_type> { private: OP1 op1; OP2 op2; OP3 op3; public: compose_f_gx_hx_t(const OP1&o1,const OP2&o2,const OP3&o3):op1(o1),op2(o2),op3(o3){} typename OP1::result_type operator()(const typename OP2::argument_type&x)const{ return op1(op2(x),op3(x)); } };
template<class OP1,class OP2,class OP3> inline compose_f_gx_hx_t<OP1,OP2,OP3> compose_f_gx_hx(const OP1&o1,const OP2&o2,const OP3&o3){ return compose_f_gx_hx_t<OP1,OP2,OP3>(o1,o2,o3); } }
namespace compose{ template<class OP1,class OP2,class OP3> class compose_f_gx_hy_t:public std::binary_function<typename OP2::argument_type,typename OP3::argument_type,typename OP1::result_type> { private: OP1 op1; OP2 op2; OP3 op3; public: compose_f_gx_hy_t(const OP1&o1,const OP2&o2,const OP3&o3):op1(o1),op2(o2),op3(o3){} typename OP1::result_type operator()(const typename OP2::argument_type&x,const typename OP3::argument_type&y)const{ return op1(op2(x),op3(y)); } };
template<class OP1,class OP2,class OP3> inline compose_f_gx_hy_t<OP1,OP2,OP3> compose_f_gx_hy(const OP1&o1,const OP2&o2,const OP3&o3){ return compose_f_gx_hy_t<OP1,OP2,OP3>(o1,o2,o3); } }
#include"compose.h" #include<iostream> #include<vector> #include<iterator> #include<algorithm> #include<string> #include<cctype> using namespace std; int main() { vector<int> coll; for(int i=0;i<7;++i) coll.push_back(i); ::transform(coll.begin(),coll.end(), ::ostream_iterator<int>(cout," "), compose::compose_f_gx(::bind2nd(::multiplies<int>(),5),::bind2nd(::plus<int>(),10)));
vector<int>::iterator iter; iter=::remove_if(coll.begin(),coll.end(), compose::compose_f_gx_hx( ::logical_and<bool>(), ::bind2nd(::greater<int>(),2), ::bind2nd(::less<int>(),5)) ); ::copy(coll.begin(),iter,::ostream_iterator<int>(cout," ")); cout<<endl;
string s("helloworld"); string sub("llowo"); string::iterator iter1; iter1=::search(s.begin(),s.end(), sub.begin(),sub.end(), compose::compose_f_gx_hy(::equal_to<int>(), ::ptr_fun(::toupper), ::ptr_fun(::toupper)));
}
|