首页 > 代码库 > 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的一个部分的学习记录。

STL学习之路之仿函数