现在的位置: 首页 > 综合 > 正文

模板之泛化仿函数(二)

2018年03月30日 ⁄ 综合 ⁄ 共 2007字 ⁄ 字号 评论关闭

实现 STL 的 BindFirst 功能

假设有个 Functor 取两个整数作为参数,你想将其中一个整数绑定为固定值,只让另一个变化。绑定会产生出一个”只取单一整数“的 Functor,如下:

void f()
{
        // Define a Functor of two arguments
        Functor<void, TYPELIST_2(int, int)> cmd1(something);
        // Bind the first argument to 10
        Functor<void, TYPELIST_1(int)> cmd2(BindFirst(cmd1, 10));
        // Same as cmd1(10,20)
        cmd2(20);
        Functor<void> cmd3(BindFirst(cmd2,10));
        // Same as cmd1(10, 30)     
        cmd3(30);
}

绑定不但可以保存”可调用体“,还可以保存它的部分参数并足部降低调用时刻所需的环境需求。这大大提高了 Functor 的表达能力,因为它可以让你包装函数和参数,无需添加作为”粘胶“之用的代码。

template <class Incoming>
class BinderFirst
	: public FunctorImpl < typename Incoming::ResultType,
	typename Incoming::ParmList::Tail >
{
	typedef Functor < typename Incoming::ResultType,
		typename Incoming::ParmList::Tail > Outgoing;
	typedef typename Incoming::Parm1 Bound;
	typedef typename Incoming::ResultType ResultType;
public:
	BinderFirst(const Incoming& fun, Bound bound)
		: fun_(fun), bound_(bound)
	{}

	BinderFirst* Clone() const
	{
		return new BinderFirst(*this);
	}

	ResultType operator()()
	{
		return fun_(bound_);
	}
	ResultType operator()(typename Outgoing::Parm1 p1)
	{
		return fun_(bound_, p1);
	}
	ResultType operator()(typename Outgoing::Parm1 p1,
		typename Outgoing::Parm2 p2)
	{
		return fun_(bound_, p1, p2);
	}
private:
	Incoming fun_;
	Bound bound_;
};
namespace Private
{
	template <class Fctor> struct BinderFirstTraits;


	template <typename R, class TList>
	struct BinderFirstTraits < Functor<R, TList> >
	{
		typedef Functor<R, TList> OriginalFunctor;


		typedef typename TL::Erase < TList, typename TL::TypeAt<TList, 0>::Result >
			::Result
			ParmList;


		typedef typename TL::TypeAt<TList, 0>::Result OriginalParm1;


		typedef Functor<R, ParmList> BoundFunctorType;


		typedef typename BoundFunctorType::Impl Impl;


	};
}


template <class Fctor>
typename Private::BinderFirstTraits<Fctor>::BoundFunctorType
	BindFirst(const Fctor& fun, typename Fctor::Parm1 bound)
{
	typedef typename
		Private::BinderFirstTraits<Fctor>::BoundFunctorType
		Outgoing;
	return Outgoing(auto_ptr<typename Outgoing::Impl>(new BinderFirst<Fctor>(fun, bound)));
}
const char* Fun(int i, int j)
{
	cout << "Fun(" << i << "," << j << ") called" << endl;
	return "0";
}


int main()
{
	Functor<const char*, TYPELIST_2(int, int)> f1(&Fun);
	Functor<string, TYPELIST_1(double)> f2(BindFirst(f1, 10));
	f2(15);
	return 0;
}

抱歉!评论已关闭.