首页 > 代码库 > STL学习之路之仿函数
STL学习之路之仿函数
STL中的仿函数(或者叫做函数对象):可以实现类似于函数一样的类型,函数最直接的调用形式就是:返回值 函数名(参数列表),仿函数实现了operator()操作符,使用类似于函数。
同时,STL还为仿函数提供了强大的配接器,也就是适配器Adapters,这些适配器本身也属于仿函数,调用方式同样类似于函数。更进一步,这些适配器可以和仿函数、函数、适配器再进行绑定、组合、适配,完成更加复杂的功能。
这部分应该是STL中最简单的部分,实现也比较简单。另外C++11标准对这部分调整比较大,我们先不考虑。暂且把它作为一个学习template的例子。
#ifndef TESTFUNCTIONAL_H #define TESTFUNCTIONAL_H namespace Test{ 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) const { return _x + _y; } }; template<class _Tp> struct minus : public binary_function<_Tp, _Tp, _Tp>{ _Tp operator()(const _Tp& _x, const _Tp& _y) const { return _x - _y; } }; template<class _Tp> struct multiplies : public binary_function<_Tp, _Tp, _Tp>{ _Tp operator()(const _Tp& _x, const _Tp& _y) const { return _x * _y; } }; template<class _Tp> struct divides : public binary_function<_Tp, _Tp, _Tp>{ _Tp operator()(const _Tp& _x, const _Tp& _y) const { return _x / _y; } }; template<class _Tp> struct modulus : public binary_function<_Tp, _Tp, _Tp>{ _Tp operator()(const _Tp& _x, const _Tp& _y) const { return _x % _y; } }; template<class _Tp> struct negate : public unary_function<_Tp, _Tp>{ _Tp operator()(const _Tp& _x) const { return -_x; } }; template <class _Tp> struct equal_to : public binary_function<_Tp,_Tp,bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return __x == __y; } }; template <class _Tp> struct not_equal_to : public binary_function<_Tp,_Tp,bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return __x != __y; } }; template <class _Tp> struct greater : public binary_function<_Tp,_Tp,bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return __x > __y; } }; template <class _Tp> struct less : public binary_function<_Tp,_Tp,bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return __x < __y; } }; template <class _Tp> struct greater_equal : public binary_function<_Tp,_Tp,bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return __x >= __y; } }; template <class _Tp> struct less_equal : public binary_function<_Tp,_Tp,bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return __x <= __y; } }; template <class _Tp> struct logical_and : public binary_function<_Tp,_Tp,bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return __x && __y; } }; template <class _Tp> struct logical_or : public binary_function<_Tp,_Tp,bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return __x || __y; } }; template <class _Tp> struct logical_not : public unary_function<_Tp,bool> { bool operator()(const _Tp& __x) const { return !__x; } }; template<class _Predicate> class unary_negate : public unary_function<typename _Predicate::argument_type, bool>{ protected: _Predicate _M_pred; public: explicit unary_negate(const _Predicate& _x):_M_pred(_x){} bool operator()(const typename _Predicate::argument_type& _x) const { return !_M_pred(_x); } }; template<class _Predicate> inline unary_negate<_Predicate> not1(const _Predicate& _pred){ return unary_negate<_Predicate>(_pred); } template<class _Predicate> class binary_negate : public binary_function<typename _Predicate::first_argument_type, typename _Predicate::second_argument_type, bool>{ protected: _Predicate _M_pred; public: explicit binary_negate(const _Predicate& _x) : _M_pred(_x) {} bool operator()(const typename _Predicate::first_argument_type& _x, const typename _Predicate::second_argument_type& _y) const{ return !_M_pred(_x, _y); } }; template<class _Predicate> inline binary_negate<_Predicate> not2(const _Predicate& _pred) { return binary_negate<_Predicate>(_pred); } //绑定一个二元操作符类的第一个操作数,也就是调用operator()参数需要传递第二个操作数 template<class _Operation> class binder1st : public unary_function<typename _Operation::second_argument_type,//派生自一元操作符类, //一元操作符的参数类型为该二元操作符类的第二个操作数类型,与需要调用的operator()参数类型一样 typename _Operation::result_type>{ protected: _Operation _op; typename _Operation::first_argument_type value; public: binder1st(const _Operation& op, const typename _Operation::first_argument_type& _x) :_op(op), value(_x){} typename _Operation::result_type operator()(const typename _Operation::second_argument_type& _y) const{ return _op(value, _y); } }; template<class _Operation, class _Tp> inline binder1st<_Operation> bind1st(const _Operation& op, const _Tp& _x){ typedef typename _Operation::first_argument_type _Arg1_type; return binder1st<_Operation>(op, _Arg1_type(_x)); } //绑定一个二元操作符类的第二个操作数,也就是调用operator()参数需要传递第一个操作数 template<class _Operation> class binder2nd : public unary_function<typename _Operation::first_argument_type,//派生自一元操作符类, //一元操作符的参数类型为该二元操作符类的第二个操作数类型,与需要调用的operator()参数类型一样 typename _Operation::result_type>{ protected: _Operation _op; typename _Operation::second_argument_type value; public: binder2nd(const _Operation& op, const typename _Operation::second_argument_type& _y) :_op(op), value(_y){} typename _Operation::result_type operator()(const typename _Operation::first_argument_type& _x) const{ return _op(_x, value); } }; template<class _Operation, class _Tp> inline binder2nd<_Operation> bind2nd(const _Operation& op, const _Tp& _y) { typedef typename _Operation::second_argument_type _Arg2_type; return binder2nd<_Operation>(op, _Arg2_type(_y)); } //f(g(x)) template<class _Operation1, class _Operation2> class unary_compose : public unary_function<typename _Operation2::argument_type, typename _Operation1::result_type> { protected: _Operation1 _M_op1; _Operation2 _M_op2; public: unary_compose(const _Operation1& op1, const _Operation2& op2) :_M_op1(op1), _M_op2(op2){} typename _Operation1::result_type operator()(const typename _Operation2::argument_type & _x) const { return _M_op1(_M_op2(_x)); } }; template<class _Operation1, class _Operation2> inline unary_compose<_Operation1, _Operation2> compose1(const _Operation1& op1, const _Operation2& op2){ return unary_compose<_Operation1, _Operation2>(op1, op2); } //f(g1(x), g2(x)) template<class _Operation1, class _Operation2, class _Operation3> class binary_compose : binary_function<typename _Operation2::argument_type, typename _Operation3::argument_type, typename _Operation1::result_type> { protected: _Operation1 _M_op1; _Operation2 _M_op2; _Operation3 _M_op3; public: binary_compose(const _Operation1& op1, const _Operation2& op2, const _Operation3& op3) :_M_op1(op1), _M_op2(op2), _M_op3(op3){} typename _Operation1::result_type operator()(typename const _Operation2::argument_type& _x) const{ return _M_op1(_M_op2(_x), _M_op3(_x)); } }; template<class _Operation1, class _Operation2, class _Operation3> inline binary_compose<_Operation1, _Operation2, _Operation3> compose2(const _Operation1& op1, const _Operation2& op2, const _Operation3& op3){ return binary_compose<_Operation1, _Operation2, _Operation3>(op1, op2, op3); } //普通单参数函数转对象 template<class _Arg, class _Result> class pointer_to_unary_function : public unary_function<_Arg, _Result>{ protected: _Result (*_pfn)(_Arg); public: pointer_to_unary_function(){} explicit pointer_to_unary_function(_Result (*pfn)(_Arg)) : _pfn(pfn){} _Result operator()(_Arg _x) const{ return _pfn(_x); }; }; template<class _Arg, class _Result> inline pointer_to_unary_function<_Arg, _Result> ptr_fun(_Result (*pfn)(_Arg)){ return pointer_to_unary_function<_Arg, _Result>(pfn); } //普通2参数函数转对象 template<class _Arg1, class _Arg2, class _Result> class pointer_to_binary_function : public binary_function<_Arg1, _Arg2, _Result> { protected: _Result (*_pfn)(_Arg1, _Arg2); public: pointer_to_binary_function(_Result (*pfn)(_Arg1, _Arg2)) :_pfn(pfn){} _Result operator()(_Arg1 _x, _Arg2 _y) const{ return _pfn(_x, _y); } }; template<class _Arg1, class _Arg2, class _Result> inline pointer_to_binary_function<_Arg1, _Arg2, _Result> ptr_fun(_Result (*pfn)(_Arg1, _Arg2)){ return pointer_to_binary_function<_Arg1, _Arg2, _Result>(pfn); } //类函数,类对象指针 template<class _Ret, class _Tp> class mem_fun_t : public unary_function<_Tp*, _Ret>{ protected: _Ret (_Tp::*_pfn)(); public: explicit mem_fun_t(_Ret (_Tp::*pfn)()) : _pfn(pfn){} _Ret operator()(_Tp* _p) const{ return (_p->*_pfn)(); } }; //类const函数,类对象指针 template<class _Ret, class _Tp> class const_mem_fun_t : public unary_function<const _Tp*, _Ret>{ protected: _Ret (_Tp::*_pfn)() const; public: explicit const_mem_fun_t(_Ret (_Tp::*pfn)() const): _pfn(pfn) {} _Ret operator()(const _Tp* _p) const{ return (_p->*_pfn)(); } }; //类函数,类对象引用 template<class _Ret, class _Tp> class mem_fun_ref_t : public unary_function<_Tp, _Ret>{ protected: _Ret (_Tp::*_pfn)(); public: explicit mem_fun_ref_t(_Ret (_Tp::*pfn)()) : _pfn(pfn){} _Ret operator()(_Tp& _p) const{ return (_p.*_pfn)(); } }; //类const函数,类对象引用 template<class _Ret, class _Tp> class const_mem_fun_ref_t : public unary_function<_Tp, _Ret>{ protected: _Ret (_Tp::*_pfn)(); public: explicit const_mem_fun_ref_t(_Ret (_Tp::*pfn)() const) : _pfn(pfn){} _Ret operator()(const _Tp& _p) const{ return (_p.*_pfn)(); } }; //含参数省略...... template<class _Ret, class _Tp> inline mem_fun_t<_Ret, _Tp> mem_fun(_Ret (_Tp::*pfn)()){ return mem_fun_t<_Ret, _Tp>(pfn); } template<class _Ret, class _Tp> inline const_mem_fun_t<_Ret, _Tp> mem_fun(_Ret (_Tp::*pfn)() const){ return const_mem_fun_t<_Ret, _Tp>(pfn); } template<class _Ret, class _Tp> inline mem_fun_ref_t<_Ret, _Tp> mem_fun_ref(_Ret (_Tp::*pfn)()){ return mem_fun_ref_t<_Ret, _Tp>(pfn); } template<class _Ret, class _Tp> inline const_mem_fun_ref_t<_Ret, _Tp> mem_fun_ref(_Ret (_Tp::*pfn)() const){ return const_mem_fun_ref_t<_Ret, _Tp>(pfn); } } #endif //TESTFUNCTIONAL_H实现方面我写了一部分,一些相似的偷懒省略了,如果想看完整版的可以下载源码。另外,我还对它做了一些测试:
#include "TestFunctional.h" #include <stdlib.h> #include <iostream> using namespace std; class TestClass{ public: void testFun() { cout << "testfun" << endl; } void testFunC() const { cout << "testfun1 const" << endl;} }; int main(int argc, char *argv[]) { typedef Test::less<int> Op_less; int opVal = 6; int val = 4; // 6 < x Test::binder1st<Op_less > bd1 = Test::bind1st<Op_less, double>(Op_less(), opVal); cout << opVal << " less than " << val << '\t' << boolalpha << bd1(val) << endl; // x < 6 ,即 6 > x Test::binder2nd<Op_less > bd2 = Test::bind2nd<Op_less, double>(Op_less(), opVal); cout << val << " less than " << opVal << '\t' << boolalpha << bd2(val) << endl; //f(x) = 3 * x, g(x) = x + 2 ==> f(g(x)) = (x + 2) * 3; typedef Test::plus<int> Op_plus; typedef Test::multiplies<int> Op_mult; cout << Test::compose1<Test::binder1st<Op_mult>, Test::binder2nd<Op_plus> >( Test::bind1st<Op_mult, int>(Op_mult(), 3), Test::bind2nd<Op_plus, int>(Op_plus(), 2))(val) << endl; //f(x, y) = x * y, g1(x) = x + 2, g2(x) = 6 - x ==>f(g1(x), g2(x)) = (x + 2) * (6 - x) typedef Test::minus<int> Op_minus; cout << Test::compose2<Op_mult, Test::binder2nd<Op_plus>, Test::binder1st<Op_minus> >(Op_mult(), Test::bind2nd<Op_plus, int>(Op_plus(), 2), Test::bind1st<Op_minus, int>(Op_minus(), 6))(val) << endl; TestClass tc1; Test::mem_fun(&TestClass::testFun)(&tc1); Test::mem_fun(&TestClass::testFunC)(&tc1); system("pause"); return 1; }
测试结果一并附上吧,我没有在gcc下测试,仅仅是在vs2010中运行了。
STL学习之路之仿函数
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。