find_if(vec.begin(),vec.end(),bind2nd(modulus<int>(),2));modulus<int>()初始化一个二元的函数对象,bind2nd函数把‘2’赋予其第二个参数,返回一个一元函数对象,即判断一个整数是否为偶数。这个语句的目的即找出容器vec中第一个偶数。
template<typename Operation,typename T> binder1st bind1st(const Operation &op, const T &t) { return binder1st<Operation>(op,typename Operation::first_argument_type(t)); }
template<typename Operation,typename T> binder1st bind2nd(const Operation &op, const T &t) { return binder2nd<Operation>(op,typename Operation::second_argument_type(t)); }先不管具体细节,后面马上会说到。我们只关注函数的实现,很容易看出返回的分别是类binder1st<Operation>和binder2nd<Operation>的对象,即我们所说的函数适配器。
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; };这两个结构定义了几个类型成员,来表示函数对象参数和返回值的类型。其中unary_function代表一元函数对象,binary_function代表二元函数对象。通过让我们自定义的函数对象继承相应的结构,即可在函数适配器中使用。标准库的函数对象正是这样设计的,我们拿适配器binder1st作为例子来说明下,类binder1st如下:
template<class Operation> class binder1st: public unary_function<typename Operation::second_argument_type, typename Operation::return_type> { public: binder1st(const Operation &op, const typename Operation::first_argument_type &arg): operation(op),arg_1st(arg) {} typename Operation::return_type operator() (const typename Operation::second_argument_type &arg_2nd) const { return operation(arg_1st,arg_2nd); } private: Operation operation; typename Operation::first_argument_type arg_1st; };适配器通过接受一个二元的函数对象(Operation)和一个该二元函数对象第一个参数类型的值(arg)调用构造函数。在其重载的"()"操作符函数中,只接受一个参数,对应其基类unary_function的argument_type,返回类型为unary_function的return_type。类定义中频繁用到了typename Operation::first_argument、typename Operation::second_argument_type及typename Operation::result_type,充分说明了对Operation的要求,只要Operation继承了binary_function即可。我们以一个计算pow(x,y)的函数对象为例子演示一下:
template<typename T1, typename T2> class Pow: public binary_function<T1,T2,T1> { public: T1 operator() (T1 base, T2 exp) const { return std::pow(base,exp); } };比如我们需要一个计算任意数字立方的函数对象,即可通过bind2nd(Pow<float,int>(),3)来得到。
template<typename H,typename F,typename G> class MyAdapter: unary_function<typename F::argument_type, typename H::return_type> { public: MyAdapter(const H &h, const F &f, const G &g):m_h(h),m_f(f),m_g(g) {} typename H::return_type operator() (const typename F::argument_type &x) const { return m_h(m_f(x),m_g(x)); } private: H m_h; F m_f; G m_g; };
(完)