本文只通过简单的例子介绍函数配接器是如何工作的。
函数对象直接应用的地方较少,它配合实现一些算法(作为算法的参数),于是便有函数配接器。因为通过函数对象,几乎可以实现我们所要的表达式,那么某些算法也确实可以通过函数对象,来得到我们所预期(把预期放在表达式中)的结果。
展示一段代码:
/*摘自C++ standard STL。*/
......
int ia[] = {11,12,13,1,2,3,4,5,6,7};
vector<int> iv(ia,ia+10);
cout << count_if(iv.begin(),iv.end(),bind2nd(less<int>(),10)) << endl;
......
7
请按任意键继续. . .
我们可以试着一步一步展开count_if()函数,
/*摘自C++ standard STL。*/
template<class _InIt,
class _Pr> inline
typename iterator_traits<_InIt>::difference_type
count_if(_InIt _First, _InIt _Last, _Pr _Pred)/*这里。*/
{ // count elements satisfying _Pred
return _Count_if(_CHECKED_BASE(_First), _CHECKED_BASE(_Last), _Pred);
}
/*count_if()的底层函数。*/
template<class _InIt,
class _Pr> inline
typename iterator_traits<_InIt>::difference_type
_Count_if(_InIt _First, _InIt _Last, _Pr _Pred)
{ // count elements satisfying _Pred
_DEBUG_RANGE(_First, _Last);
_DEBUG_POINTER(_Pred);
typename iterator_traits<_InIt>::difference_type _Count = 0;
for (; _First != _Last; ++_First)
if (_Pred(*_First))
++_Count;
return (_Count);
}
其中,_Pred就是函数对象binder2nd,它在return (std::binder2nd<_Fn2>(_Func, _Val));语句中,被构造出来,同时它重载了“()”操作符,再来看看bind2nd和binder2nd:
/*摘自C++ standard STL。*/
// TEMPLATE CLASS binder2nd
template<class _Fn2>
class binder2nd
: public unary_function<typename _Fn2::first_argument_type,
typename _Fn2::result_type>
{ // functor adapter _Func(left, stored)
public:
typedef unary_function<typename _Fn2::first_argument_type,
typename _Fn2::result_type> _Base;
typedef typename _Base::argument_type argument_type;
typedef typename _Base::result_type result_type;
binder2nd(const _Fn2& _Func,
const typename _Fn2::second_argument_type& _Right)
: op(_Func), value(_Right)
{ // construct from functor and right operand
}
result_type operator()(const argument_type& _Left) const
{ // apply functor to operands
return (op(_Left, value));
}
result_type operator()(argument_type& _Left) const
{ // apply functor to operands
return (op(_Left, value));
}
protected:
_Fn2 op; // the functor to apply
typename _Fn2::second_argument_type value; // the right operand
};
// TEMPLATE FUNCTION bind2nd
template<class _Fn2,
class _Ty> inline
binder2nd<_Fn2> bind2nd(const _Fn2& _Func, const _Ty& _Right)
{ // return a binder2nd functor adapter
typename _Fn2::second_argument_type _Val(_Right);
return (std::binder2nd<_Fn2>(_Func, _Val));
}
bind2nd()是辅助函数,为的是使用binder2nd(真正的主角)更为方便。
count_if(iv.begin(),iv.end(),bind2nd(less
count_if()函数在处理每一个元素的时候,实际调用binder2nd的“()”运算符重载函数,而这个函数当中有调用了其内部操作成员op(其又是一个函数对象less
总结就是count_if()调用bind2nd()函数,bind2nd()函数实际产生binder2nd函数对象,返回给count_if()做为参数,count_if()再调用更为底层的函数_Count_if()函数。
我们从count_if()的源代码可以得知,count_if(iv.begin(),iv.end(),bind2nd(less
bool less10(int i)
{
if(i<10)
return true;
return false;
}
......
int ia[] = {11,12,13,1,2,3,4,5,6,7};
vector<int> iv(ia,ia+10);
cout << count_if(iv.begin(),iv.end(),less10) << endl;
......
此时,count_if()中的_Pred就是一函数指针了。所以,函数对象还是可以用一般函数指针替换的。
STL实现的函数配接器:http://www.cplusplus.com/reference/std/functional/
本文完 2012-10-26
Dylan http://daoluan.github.io/
26 October 2012 会持续更新