在学习的过程中看到下面的一条语句:
count_if ( vec.begin() , vec.end() , not1 ( bind2nd ( less_equal<int>() , 10 )));
对于泛型算法count_if它的实现如下:
Template<class InputIterator, class Predicate>
Typename iterator_traits<InputIterator>::difference_type
Count_if ( InputIterator first , InputIterator last , Predicate pred){
Typename iterator_traits<InputIterator>::difference_type n=0;
For ( ; first!=last ; ++first)}
If(pred(*first))
++n;
Return n;
}
因此对于第三个参数,传进去的predicate它应当转换成
not1(bind2nd(less_equal<int>(),10))()(*first)
对其中的
not1(bind2nd(less_equal<int>(),10))
用到了binary functor : less_equal及binder:bind2nd和negator:not1。它们在STL中的实现如下,可以通过分析源代码来了解它们的使用。
首先定义所有binary functor的祖先类binary_functor:
Template<typename FstArgType, typename SndArgType, typename ResultType>
Struct binary_functor {
Typedef typename FstArgType first_arg_type;
Typedef typename SndArgType second_arg_type;
Typedef typename ResultType result_type;
};
所有的binary functor都要继承这个类,
Template<typename Type >
Struct less_equal: public binary_functor<Type, Type, bool> {
Public:
Bool operator () (const Type &lh, const Type &rh) const
//函数应尽量为const型,增加参数范围
{ return lh<=rh;}
};
通过这样的定义之后,可以这样使用functor less_equal了:
Less_equal<int> le;cout<<le(4,6)<<endl;
或者使用临时对象cout<<less_equal<int>()(4,6)<<endl;
而所谓的绑定器binder,就是将它的参数,绑定到一个functor之上,如bind2nd(less_equal<int>(),10),它便是将10绑定到less_equal的第二个参数之上.
它的源代码如下:
Template<class BinaryFunctor>
Class binder2nd:public unary_function<typename BinaryFunctor::first_arg_type,
Typenamte BinaryFunctor::result_type>{
Protected:
BinaryFunctor functor;
Typename BinaryFunctor::second_arg_type value;
Public:
Binder2nd(const BinaryFunctor &functor,
Const typename BinaryFunctor::second_arg_type &second)
:functor(functor),value(second){};
Typename BinaryFunctor::result_type
Operator()(const typename BinaryFunctor::first_arg_type & first) const{
Return functor(first,value);
};
};
这是绑定器binder2nd,而我们经常使用的是绑定函数bind2nd,它不过是封装了binder2nd,实现如下:
Template<class BinaryFunctor, class T>
Inline binder2nd<BinaryFunctor>
bind2nd(const BinaryFunctor &functor,const T &x){
typedef typename BinaryFunctor::second_arg_type second;
return binder2nd<BinaryFunctor>(funcotr,second(x));
}
通过观察绑定器的实现,我们就可以知道其实binder2nd也是个functor,不过是一元functor,它的作用是将为一个二元functor绑定一个值作为二元functor的第二个参数。
所以
bind2nd(less_equal<int>(),10))()(*first)等效于
less_equal<int> functor;
binder2nd<less_equal<int> > binder(functor,10);
binder(*first);转换成底层代码就是funcotr(first,10);
在了解了这些之后,我们就可以不参照源代码,定义自己的not1出来了。下面是我自己定义的:
Template<class UnaryFunctor>
Class noter1: public unary_functor< typename UnaryFunctor::arg_type, bool>{
Protected:
UnaryFunctor functor;
Public:
Explicit noter1(UnaryFunctor & functor):functor(functor){};
Bool operator()(const typename UnaryFunctor::arg_type &arg) const {
Return !functor(arg);
};
};
再定义not1函数:
Template<class UnaryFunctor>
Inline noter1<UnaryFunctor> not1(const UnaryFunctor &functor){
Return noter1<UnaryFunctor>(funcotr);
}