標籤:c++ stl function
STL中的仿函數(或者叫做函數對象):可以實作類別似於函數一樣的類型,函數最直接的調用形式就是:返回值 函數名(參數列表),仿函數實現了operator()操作符,使用類似於函數。
同時,STL還為仿函數提供了強大的配接器,也就是適配器Adapters,這些適配器本身也屬於仿函數,調用方式同樣類似於函數。更進一步,這些適配器可以和仿函數、函數、適配器再進行綁定、組合、適配,完成更加複雜的功能。
這部分應該是STL中最簡單的部分,實現也比較簡單。另外C++11標準對這部分調整比較大,我們先不考慮。暫且把它作為一個學習template的例子。
#ifndef TESTFUNCTIONAL_H#define TESTFUNCTIONAL_Hnamespace 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 < xTest::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 > xTest::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的一個部分的學習記錄。
STL學習之路之仿函數