stl算法庫多數算法只能提供一個參數給綁定函數,如for_each函數。如果想打印vector中的每一個元素,用for_each實現方式代碼如下:
#include <iostream>
#include <algorithm>
#include <vector>
struct print
{
voidoperator()(const int x){ std::cout<< x << std::endl; }
};
int main(int argc, char **argv)
{
std::vector<int>vec{ 1, 3, 5, 7, 9 };
std::for_each(vec.begin(),vec.end(), print());
return0;
}
但如果綁定函數要求有兩個,或多個輸入參數呢?例如,想對vector中的每個元素值增加100,很明顯,僅僅靠for_each算法提供的一個參數無法實現。因此,需要給綁定函數增加一個成員變量,代碼實現如下:
#include <iostream>
#include <algorithm>
#include <vector>
struct print
{
voidoperator()(const int x) { std::cout<< x << std::endl; }
};
struct add
{
inti;
add(int_i) : i(_i) {}
intoperator()(int &x) { x += i; return x; }
};
int main(int argc, char **argv)
{
std::vector<int>vec{ 1, 3, 5, 7, 9 };
std::for_each(vec.begin(),vec.end(), print());
std::for_each(vec.begin(),vec.end(), add(100));
std::for_each(vec.begin(),vec.end(), print());
return0;
}
除了上面的方式,還可以使用std::bind1st,std::bind2nd,使用std::bind2nd代碼如下:
#include <iostream>
#include <string>
#include <algorithm> //std::for_each
#include <xfunctional> //std::bind2nd
#include <vector>
struct print
{
voidoperator()(const int x)
{
std::cout<< x << std::endl;
}
};
struct add : public std::binary_function< int, int, int >
{
intoperator()(int &x, const int &y) const { x += y; return x; } //必須爲const函數
};
int main(int argc, char **argv)
{
std::vector<int>vec{ 1, 3, 5, 7, 9 };
std::for_each(vec.begin(),vec.end(), print());
std::for_each(vec.begin(),vec.end(), std::bind2nd(add(), 100));
std::for_each(vec.begin(),vec.end(), print());
return0;
}
注意add的()(函數操作符)操作符必須爲const函數,否則會出現下面的錯誤:
errorC3848: 具有類型“const add”的表達式會丟失一些 const-volatile 限定符以調用“int add::operator ()(int &,const int &)”
std::bind是如何將100綁定到第二個參數的呢?先看看std::binary_function,實現如下:
template<class _Arg1,
class_Arg2,
class_Result>
structbinary_function
{ // base class for binary functions
typedef_Arg1 first_argument_type;
typedef_Arg2 second_argument_type;
typedef_Result result_type;
};
不難發現該類僅定義了三個類型,第一個參數類型,第二個參數類型,返回值類型。這三個類型到底有什麼作用呢?再看看std::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));
}
_Fn2實際就是傳入的仿函數類型binary_function的派生類,裏面用到了second_argument_type(綁定參數類型),並通過_Fn2對象和綁定參數構建了一個binder2nd對象,binder2nd實現如下:
template<class _Fn2>
classbinder2nd
:public unary_function<typename _Fn2::first_argument_type,
typename_Fn2::result_type>
{ // functor adapter _Func(left, stored)
public:
typedefunary_function<typename _Fn2::first_argument_type,
typename_Fn2::result_type> _Base;
typedeftypename _Base::argument_type argument_type;
typedeftypename _Base::result_type result_type;
binder2nd(const_Fn2& _Func,
consttypename _Fn2::second_argument_type& _Right)
:op(_Func), value(_Right)
{ // construct from functor and rightoperand
}
result_typeoperator()(const argument_type& _Left) const
{ // apply functor to operands
return(op(_Left, value));
}
result_typeoperator()(argument_type& _Left) const
{ // apply functor to operands
return(op(_Left, value));
}
protected:
_Fn2op; // the functor to apply
typename_Fn2::second_argument_type value; //the right operand
};
binder2nd保存仿函數對象op,和綁定參數,並重載函數操作符,函數操作符均有一個參數,即容器元素,其類型爲argument_fisrt_type。在操作符調用op(容器元素, 綁定參數),其原理和帶成員變量i的仿函數一樣。binder2nd的基類unary_function實現也很簡單:
template<class _Arg,
class_Result>
structunary_function
{ // base class for unary functions
typedef_Arg argument_type;
typedef_Result result_type;
};
該類僅僅定義了返回類型和參數類型(for_each傳入參數)。
bind2nd使用原理如下:
-
從std::binary_function派生子類
-
通過bind2nd將派生類和綁定參數綁定到一起,構造binder2nd對象
-
for_each調用仿函數binder2nd對象。
對於爲什麼會有bind1st和bind2nd之分,是因爲有些操作是區分左值和右值的,如:std::less。如果參數更多,怎麼辦?定義結構體,綁定結構體變量。因爲bind支持綁定參數和容器元素類型不同。