仿函数与函数配接器

转至: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 )));
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值