概述
bind1st 和 bind2nd 函数把一个二元函数对象绑定成为一个一元函数对象。但是由于原来的二元函数对象接受两个参数,在绑定成为一元函数对象时需要将原来两个参数中的一个绑定下来,也就是通过绑定二元函数对象的一个参数使之成为一元函数对象的参数。bind1st是绑定第一个参数,bind2nd则是绑定第二个参数。
这也就是说,bind1st 和 bind2nd 函数把less<int>这样的二元函数对象绑定成一个一元函数对象,现在只接受一个参数。
下面先看一下bind2nd的源代码
//这个是实际的配接器对象形式
template <class Operation>
class binder2nd
: public unary_function<typename Operation::first_argument_type,
typename Operation::result_type> {
protected:
Operation op;
typename Operation::second_argument_type value;
public:
binder2nd(const Operation& x,
const typename Operation::second_argument_type& y)
: op(x), value(y) {}
typename Operation::result_type
operator()(const typename Operation::first_argument_type& x) const {
return op(x, value);
}
};
//这个是对外接口
template <class Operation, class T>
inline binder2nd<Operation> bind2nd(const Operation& op, const T& x) {
typedef typename Operation::second_argument_type arg2_type;
return binder2nd<Operation>(op, arg2_type(x));
}
class Operation代表的是一个二元函数对象。对外接口配接器bind2nd接受两个参数,一个是二元函数对象,另一个是一个普通值,这个值作为二元函数对象的第二个参数绑定到了一元函数对象,使其成为一元函数对象的参数。类binder2nd继承了unary_function变成了一元函数对象。
binder2nd(const Operation& x,
const typename Operation::second_argument_type& y)
: op(x), value(y) {}
上面这个是函数对象的构造函数的参数类型。所以,对外接口bind2nd中给binder2nd传的参数是(op,arg2_type(x)),代表了二元函数对象的第二个参数。这个概念必须分清,否则就理解不了bind2nd的过程。
bind1st的源代码
template <class Operation>
class binder1st
: public unary_function<typename Operation::second_argument_type,
typename Operation::result_type> {
protected:
Operation op;
typename Operation::first_argument_type value;
public:
binder1st(const Operation& x,
const typename Operation::first_argument_type& y)
: op(x), value(y) {}
typename Operation::result_type
operator()(const typename Operation::second_argument_type& x) const {
return op(value, x);
}
};
template <class Operation, class T>
inline binder1st<Operation> bind1st(const Operation& op, const T& x) {
typedef typename Operation::first_argument_type arg1_type;
return binder1st<Operation>(op, arg1_type(x));
}
原理与bind2nd一样,只不过是binder1st绑定的是二元函数对象的第一个参数而已。
举例
int main()
{
vector<int> v{ 1,8,6,9,3 ,10,11};
//绑定的是第二个参数,所以结果就是<7,即找比7小的元素个数
auto n = count_if(v.begin(), v.end(), bind2nd(less<int>(), 7));
//绑定的是第一个参数,所以结果就是7<,即找比7大的元素个数
auto m = count_if(v.begin(), v.end(), bind1st(less<int>(), 7));
cout << n << endl;
cout << m << endl;
system("pause");
return 0;
}
说明:
bind2nd(less<int>(),7),less<int>()和7是bind2nd的构造函数所需要的两个参数,然后执行Pred(*_First),这时候就引起了运算符()的重载,此时这个*_First就是[first,last)。
count_if的源代码
指定操作(一个仿函数)pred实施于[first,last)区间内的每一个元素身上,并将“造成pred之计算结果为true”的所有元素的个数返回。
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_PTR(_First, _Last, _Pred);
return (_Count_if(_Unchecked(_First), _Unchecked(_Last), _Pred));
}
template<class _InIt,
class _Pr> inline
typename iterator_traits<_InIt>::difference_type
_Count_if(_InIt _First, _InIt _Last, _Pr _Pred)
{ // count elements satisfying _Pred
typename iterator_traits<_InIt>::difference_type _Count = 0;
for (; _First != _Last; ++_First)
if (_Pred(*_First))//如果元素带入pred的运算结果为true
++_Count;//计数器累加一
return (_Count);
}