函数对象对于stl这个以迭代器为基石的库的重要性不言而喻
//函数对象的重要性不言而喻,尤其是对于stl这个以迭代器为基石的库 //定义一个函数对象,实现两数相加 template<class _Tp> struct plus { _Tp operator()(const _Tp& __x,const _Tp& __y){return __x+__y;} }; //我们可以使用plus(x,y); //假设我们需要的是-(x+y),怎么算? template<class _Tp> struct negative_plus { _Tp operator()(const _Tp& __x,const _Tp& __y){return -(__x+__y);} }; //对于这种非常简单的函数对象,我们可以重写,如果非常复杂的怎么办?这里就引出了配接器的概念,我们定义一个配接器 //它可以返回plus(x,y)的负数,当然它的参数就是plus函数对象: template<class _Func> struct negate { //参数是什么?返回值是什么类型?怎么由plus对象得到_Tp? }; //上述的问题是配接器的普遍问题,怎么解决? //诚然自己写的函数对象也可以用,但是,却不能与已定义好的函数对象很好的兼容,尤其是与配接器的兼容性。如果要写出 //兼容性好的,并且能使用配接器的函数对象,就要遵循规范:函数对象继承于下面的两个类! //一元函数对象的基类:参数类型和返回结果类型 template<class _Arg,class _Result> struct unary_function { typedef _Arg argument_type; typedef _Result result_type; }; //二元函数对象的基类 template<class _Arg1,class _Arg2,class _Result> struct binary_function { typedef _Arg1 first_argument_type; typedef _Arg2 second_argument_type; typedef _Result result_type; }; //举个例子: template<class _Tp> struct plus :public binary_function<_Tp,_Tp,_Tp> { _Tp operator()(const _Tp& __x,const _Tp& __y){return __x+__y;} }; //配接器: template<class _Function> struct negate_binary:public binary_function<typename _Function::first_argument_type, typename _Function::second_argument_type,typename _Function::result_type> { explicit negate_binary(const _Function& __f):m_f(__f){} result_type operator()(const first_argument_type& __x,const second_argument_type& __y)const {return -(m_f(__x,__y));} protected: _Function m_f; }; //这样就可以实现各种类型的配接器了 //配接器类型二:将二元的函数对象转换为一元的函数对象,采用的方式是固定其中的一个参数,下面举例固定第一个参数 template<class _Function> struct _bind1st:public unary_function<typename _Function::second_arugument_type,typename _Function::result_type> { protected: _Function m_function; typename _Function::first_arugument_type m_first; public: bind1st(const _Function& __f,const typename _Function::first_arugument_type& __x) :m_function(__f),m_first(__x){} result_type operator()(const argument_type& __y)const {return m_function(m_first,__y);} }; //配接器类型三:组合函数对象,这是由简单的函数对象产生复杂函数对象的方法 //op1(op2(x)),op1(op2(x),op3(x)),op1(op2(x,y)),op1(op2(x),op3(y))四种,下面是第一种 //一元函数对象的组合:op1(op2(x))参数是op2的参数,结果是op1的结果 template<class _Function1,class _Function2> struct compose1:public unary_function<typename _Function2::argument_type,typename _Function1::result_type> { protected: _Function1 m_function1; _Function2 m_function2; public: compose(const _Function1& __f1,const _Function2& __f2) :m_function1(__f1),m_function2(__f2){} result_type operator()(const argument_type& __x) const{return m_function1(m_function2(__x));} }; //至此,函数对象配接器的类型就结束了,但是stl为每个配接器都提供了一个函数使用接口,这个不知道为什么这样做。。 //例如:bind1st的函数接口: template<class _Function> inline _bind1st<_Function> bind1st(const _Function& __f,const typename _Function::first_argument_type& __x) {return _bind1st<_Function>(__f,__x);} //对于函数对象,有几个问题: //1.函数指针,按理来说,对于用户,函数指针和函数对象的一样的,但是,stl中实现了很多将函数指针转化为函数对象的工具 //2,类成员函数的函数对象,这里是的使用方式是op(class),分四种情况: //类成员函数有无参数?通过指针还是引用来调用?是否返回值?const还是non-const? //举一例: template <class _Ret, class _Tp> class mem_fun_t : public unary_function<_Tp*,_Ret> { public: explicit mem_fun_t(_Ret (_Tp::*__pf)()) : _M_f(__pf) {} _Ret operator()(_Tp* __p) const { return (__p->*_M_f)(); } private: _Ret (_Tp::*_M_f)(); }; template <class _Ret, class _Tp> class const_mem_fun_t : public unary_function<const _Tp*,_Ret> { public: explicit const_mem_fun_t(_Ret (_Tp::*__pf)() const) : _M_f(__pf) {} _Ret operator()(const _Tp* __p) const { return (__p->*_M_f)(); } private: _Ret (_Tp::*_M_f)() const; }; template <class _Ret, class _Tp> class mem_fun_ref_t : public unary_function<_Tp,_Ret> { public: explicit mem_fun_ref_t(_Ret (_Tp::*__pf)()) : _M_f(__pf) {} _Ret operator()(_Tp& __r) const { return (__r.*_M_f)(); } private: _Ret (_Tp::*_M_f)(); }; template <class _Ret, class _Tp> class const_mem_fun_ref_t : public unary_function<_Tp,_Ret> { public: explicit const_mem_fun_ref_t(_Ret (_Tp::*__pf)() const) : _M_f(__pf) {} _Ret operator()(const _Tp& __r) const { return (__r.*_M_f)(); } private: _Ret (_Tp::*_M_f)() const; }; //包装函数 template <class _Ret, class _Tp> inline mem_fun_t<_Ret,_Tp> mem_fun(_Ret (_Tp::*__f)()) { return mem_fun_t<_Ret,_Tp>(__f); }