woaidongmao

文章均收录自他人博客,但不喜标题前加-[转贴],因其丑陋,见谅!~
随笔 - 1469, 文章 - 0, 评论 - 661, 引用 - 0
数据加载中……

分析stl function objects模块

从SGI的STl文档来看,STL functor(function object)模块主要分为两个部分:预先定义的functor
以及functor adaptors。除此之外,为了使客端程序员写出适用于functor adaptor的functor,STL
又定义了一系列基本上只包含typedef的空类型(例如unary_function)。用户只需要派生这些类,即
可让自己写的functor被functor adaptor使用。以下称类基类型为base functor。

base functor包括: unary_function, binary_function,分别表示只有一个参数的函数和有两个参数
的函数。实际上STL里还有一个所谓的generator,代表没有参数的函数。因为STL泛型算法一般最多
只会使用两个参数的函数,所以这里并没有定义更多参数的base functor。

可被functor adaptor使用的functor又称为adaptable function,根据参数的个数,会被命名为诸如
adaptable unary function, adaptable binary function。

一个返回值为bool的functor又被称为predicate,可被用于functor adaptor的predicate被称为
adaptable predicate。其实所谓的adaptable,只需要在类型内部typedef一些类型即可,一般包括
first_argument_type, second_argument_type, result_type。functor adaptor会使用这些定义。

预定义的functors都是些很简单的functor,基本上就是封装诸如plus, minus, equal_to之类的算术
运算,列举一个predefined functor的代码:
 

template <class _Tp>
 
struct plus : public binary_function<_Tp, _Tp, _Tp>
 
{
     _Tp
operator()(const _Tp& __x, const _Tp& __y) const  
    
{
        
return __x + __y;
     }
   
  }
;


因为从binary_function(即我所谓的base functor)派生,因此这些predefined functor也是adaptable
function。

functor adaptors里有很多有趣的东西,其实functor adaptor也是一些functor(从SGI的观点来看,一般
的C函数,函数指针都算作functor)。所不同的是,他们通常会适配(adapt)一种functor到另一种。例如:
std::binder1st,严格地说它是一个函数模板,它会把一个adaptable binary function转换为一个
adaptable unary function,并绑定一个参数。又如: std::ptr_fun,它会将一个只有一个参数的C函数
适配成一个pointer_to_unary_function的functor。

下面列举一些具体的代码:
关于base functor,基本上就只有unary_function, binary_function :
 

template <class _Arg, class _Result>
 
struct unary_function
 
{
      typedef _Arg argument_type;                   
      typedef _Result result_type;
  }
;
 


关于predefined functor,如之前列举的plus一样,再列举一个:

template <class _Tp>
 
struct greater : public binary_function<_Tp, _Tp, bool>
 
{     
    
bool operator()(const _Tp& __x, const _Tp& __y) const
    
{
        
return __x > __y;
     }
   
}
;

 
关于functor adaptors,也是我觉得比较有趣的部分,多列举几个:

template <class _Operation, class _Tp>
  inline binder1st
<_Operation>
  bind1st(
const _Operation& __fn, const _Tp& __x)
 
{
      typedef typename _Operation::first_argument_type _Arg1_type;
     
return binder1st<_Operation>(__fn, _Arg1_type(__x));
  }

 

 
bind1st返回的binder1st定义为:

template <class _Operation>
 
class binder1st : public unary_function<typename _Operation::second_argument_type,
  typename _Operation::result_type
>
 
{
 
protected:
      _Operation op;
      typename _Operation::first_argument_type value;
 
public:
      binder1st(
const _Operation& __x, const typename _Operation::first_argument_type& __y):
        op(__x), value(__y)
     
{}
      typename _Operation::result_type
     
operator()(const typename _Operation::second_argument_type& __x) const
     
{
        
return op(value, __x);
      }

     typename _Operation::result_type
    
operator()(typename _Operation::second_argument_type& __x) const
    
{
       
return op(value, __x);
     }

  }
;

 
值得一提的是,ptr_fun以及相关的pointer_to_unary_function, pointer_to_binary_function,基本上
就是用来绑定C函数的组件,不过这里采用了很基础的模板技术,因此只实现了绑定一个参数和两个参数
的C函数。这种组件类似于loki中的functor,以及boost中的bind,只是功能弱很多。与之相关的还有
mem_fun, mem_fun_ref, mem_fun1, mem_fun1_ref等,这些都是用于绑定成员函数的。另一方面,与其说
是绑定,还不如说适配,即将函数适配为functor(特指重载operator()的类)。( Mem_fun_t is an adaptor
for member functions )采用这些(ptr_fun, mem_fun之类的东西)组件,客端程序员可以很容易地将各种
运行体(Kevin似乎很喜欢发明各种名字)(C函数、成员函数)适配成functor,从而与STL泛型算法结合。
例如, SGI文档中给出的mem_fun例子:

 

struct B {
 
virtual void print() = 0;
}
;

struct D1 : public B {
 
void print() { cout << "I'm a D1" << endl; }
}
;

struct D2 : public B {
 
void print() { cout << "I'm a D2" << endl; }
}
;

int main()
{
vector
<B*> V;

V.push_back(
new D1);
V.push_back(
new D2);
V.push_back(
new D2);
V.push_back(
new D1);

for_each(V.begin(), V.end(), mem_fun(
&B::print));
}

 

 

注:以上分析基于dev-cpp中自带的stl,源代码见stl_functional.h。

posted on 2008-08-31 21:42 肥仔 阅读(294) 评论(0)  编辑 收藏 引用 所属分类: C++ 模板


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理