STL约束器之bind2nd(x, y)实例解析

今天看到STL(标准模板库)里的一个函数,也就是一个约束器--bind2nd(x, y),这个是一个模板函数,stl里面不止这么一个约束器,比如bind1st(x, y),相对而言bind2nd复杂一点,就谈一下这个函数这里。

在看这篇文章之前,建议先看看相关的资料,要求了解类模板及函数模板,容器,拟函数(仿函数或者称为函数对象),如果不了解基本的c++知识,那就不要看了,我用msvc讲解,sgi stl的stl其实差不多。

先看两个定义:

图1:

template < class_Arg , class_Result >
structunary_function{
typedef_Argargument_type;
typedef_Resultresult_type;
};

template
< class_Arg1 , class_Arg2 , class_Result >
structbinary_function{
typedef_Arg1first_argument_type;
typedef_Arg2second_argument_type;
typedef_Resultresult_type;
};

这里unary_function和binary_function是我们后面要讲到的,而且stl里面的约束器,适配器等很多东西都用到这定义。

接着是约束器的定义,在functional头文件里面, 如下:

图2:

// TEMPLATEFUNCTIONbind2nd
template < class _Fn2,
class _Ty > inline
binder2nd
< _Fn2 > bind2nd( const _Fn2 & _Func, const _Ty & _Right)
... {//returnabinder2ndfunctoradapter
typename_Fn2::second_argument_type_Val(_Right);
return(std::binder2nd<_Fn2>(_Func,_Val));
}

std::binder2nd<_Fn2>是一个类定义,也在同一个头文件下面,定义如下:

图3:

template < class _Fn2 >
class binder2nd
:
public unary_function < typename_Fn2::first_argument_type,
typename_Fn2::result_type
>
... {//functoradapter_Func(left,stored)
public:
typedefunary_function
<typename_Fn2::first_argument_type,
typename_Fn2::result_type
>_Base;
typedeftypename_Base::argument_typeargument_type;
typedeftypename_Base::result_typeresult_type;

binder2nd(
const_Fn2&_Func,
consttypename_Fn2::second_argument_type&_Right)
:op(_Func),value(_Right)
...{//constructfromfunctorandrightoperand
}


result_type
operator()(constargument_type&_Left)const
...{//applyfunctortooperands
return(op(_Left,value));
}


result_type
operator()(argument_type&_Left)const
...{//applyfunctortooperands
return(op(_Left,value));
}


protected:
_Fn2op;
//thefunctortoapply
typename_Fn2::second_argument_typevalue;//therightoperand
}
;

说到这里

template<class _Fn2>
class binder2nd
: public unary_function<typename _Fn2::first_argument_type,
typename _Fn2::result_type> 就要注意了,binder2nd类由unary_function类派生, 用到了_Fn2,而_Fn2一般的就是用到前面的binary_function类定义。

说到这里,都还没有接触到约束器bind2nd(x,y),那就再等一会,再看看拟函数的一个使用,实例一:

图4:

struct club ... {
stringss;
club(
stringa="ohyeah"):ss(a)...{}
~club()...{}
booloperator()(clubc)...{
returnc.ss==ss;
}

friendostream
&operator<<(ostream&os,club&c);
}
;

ostream
& operator << (ostream & os,club & c) ... {
returnos<<c.ss;
}


int main() ... {
list
<club>a;
list
<club>b[2];
a.push_back(st(
"a11"));
a.push_back(st(
"a22"));
a.push_back(st(
"a33"));
a.push_back(st(
"a44"));
list
<club>::iteratorp=find_if(a.begin(),a.end(),club());
//p++;
for(;p!=a.end();p++)...{
cout
<<*p<<endl;
}

}

看看find_if函数定义(头文件algorithm中):

图5:

template < class _InIt,
class _Pr > inline
_InIt_Find_if(_InIt_First,_InIt_Last,_Pr_Pred)
... {//findfirstsatisfying_Pred
_DEBUG_RANGE(_First,_Last);
_DEBUG_POINTER(_Pred);
for(;_First!=_Last;++_First)
if(_Pred(*_First))
break;
return(_First);
}


template
< class _InIt,
class _Pr > inline
_InItfind_if(_InIt_First,_InIt_Last,_Pr_Pred)
... {//findfirstsatisfying_Pred
_ASSIGN_FROM_BASE(_First,
_Find_if(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Pred));
return(_First);
}


看看这一部分就晓得了:
for (;_First != _Last; ++ _First)
if (_Pred( * _First))
break ;
return (_First);
find_if的第三个参数被用作,拟函数调用

上面的代码我想研究过stl的都明白是什么意思,我定义了一个club类,再find_if函数里面的第三个参数就是一个类对象,临时的,当iterator p移动到a.begin(), a.end()之间时,find_if函数就会调用club类里面定义的operator ()重载,调用拟函数,而且给拟函数传入(*p),这里是一个club对象,这里要记住一点,就是拟函数的参数需要传值,由调用函数传值!

在看了一个简短的拟函数的使用后,我们进入约束器的使用,实例二:

图6:

#include < iostream >
#include
< list >
#include
< algorithm >
#include
< string >
#include
< functional >

using namespace std;
int main() ... {
list
<int>a;
a.push_back(
11);
a.push_back(
22);
list
<int>::iteratorp=find_if(a.begin(),a.end(),bind2nd(less<int>(),7));
}

代码中的bind2nd(less<int>(), 7)在图2处过后就变成了

图7

list < int > ::iteratorp = find_if(a.begin(),a.end(),bind2nd(less < int > (), 7 ))
||
||
list
< int > ::iteratorp = find_if(a.begin(),a.end(),binder2nd < ** > (less < int > (), 7 ))

这里binder2nd
< **> (less < int > , 7 )其实就是一个binder2nd类临时对象,打星星符号的地方是表示binder2nd类使用的模板类型,这个要通过后面的模板类型推断。

在图3中可以看到binder2nd的构造函数:

binder2nd(
const _Fn2 & _Func,
const typename_Fn2::second_argument_type & _Right)
:op(_Func),value(_Right)
... {//constructfromfunctorandrightoperand
}

less<int>()传值给op,一个_Fn2类型的变量,7传值给value,一个int型值。

看less类定义,来推断_Fn2的具体类型。

图8:

template < class _Tp >
struct less: public binary_function < _Tp,_Tp, bool >
... {
booloperator()(const_Tp&__x,const_Tp&__y)const
...{
return__x<__y;
}

}

由此推断,_Tp是int型

那么图7里面的binder2nd< ** >(less<int>(), 7)可以推断为
binder2nd<_Fn2<int, int, bool> > >(less<int>(), 7), 应该要知道,这个就是一个临时对象,这个临时对象里面的op = less<int> (), value = 7,那么它就要调用binder2nd里面的拟函数:

result_type operator ()(argument_type & _Left) const
......
... {//applyfunctortooperands
return(op(_Left,value));
}

_Left有外界传入值,也就是开始的find_if(……)函数传入。
那么这个函数返回之后变成了:


find_if(a.begin(),a.end(),op(_Left,
7 )) // op用less<int>()对象替换之后
||
find_if(a.begin(),a.end(),less
< int > ()(_Left, 7 ))

less
< int > ()(_Left, 7 )又是一个拟函数,又要调用相应的operator()操作符。

这个操作符号在头文件
< functional > 里面定义,图8里面有。

bool operator ()( const _Tp & __x, const _Tp & __y) const
... {
return__x<__y;
}


设p为a.begin(),a.end(),之间一个指针,那么find_if(a.begin(),a.end(),less
< int > ()(_Left, 7 ))
在此演变为:
find_if(a.begin(),a.end(),less
< int > ()( * p, 7 ))
再次演变为:
find_if(a.begin(),a.end(),less
< int > :: operator ()( * p, 7 )



到此就分解到最原始的状态了,也就很简单了,就是一个简简单单的拟函数的问题了。

水平有限,多多指教!

你可能感兴趣的:(C++,c,C#,OS)