struct printx: public binary_function<int, int, int >
{
int operator()(int a, int b)const
{
cout<<a+b<<endl;
return a+b;
}
};
int main()
{
vector<int> my;
my.push_back(0);
my.push_back(1);
my.push_back(2);
copy(my.begin(), my.end(), ostream_iterator<int>(cout, " "));
cout<<"/n-----"<<endl;
for_each(my.begin(),my.end(), bind2nd(printx() , 3) );
return 0;
}
以前在使用stl的过程中发现bind1st和bind2nd这两个函数,
当时不太理解什么意思,今天在网上查了一下相关资料发现竟然很简单,
下面我就具体解释一下他们的用法。
bind1st和bind2nd函数用于将一个二元算子(binary functor,bf)
转换成一元算子(unary functor,uf)。为了达到这个目的,
它们需要两个参数:要转换的bf和一个值(v)。
可能这么解释以后大家还不是很清楚,那么就说点白话吧。
我们在做比较的时候所写的表达式像 x > k ,x < k,这里的
k是一个参数表示你程序里面的表达式要和k值去比较。
上面这两个表达式对应的应该是bind2nd ,简单的理解就是把
k作为比较表达式的第二个参数。如果使用bind1st则对应的
表达式是 k > x,k < x,也就是把k作为比较表达式的第一个参数。
大家可能会注意到这里面没有=的比较,先别着急,
后面将会说道如何实现=的比较。先举两个例子看看 bind1st和bind2nd的用法。
int a[] = {1, 2, 100, 200};
std::vector< int> arr(a, a + 4);
// 移除所有小于100的元素
arr.erase( std::remove_if( arr.begin(), arr.end(),
std::bind2nd( std::less< int>(), 100)), arr.end());
这里的比较表达式相当于arr.value < 100
如果用bind1st则表达的意思就恰恰相反
// 移除所有大于100的元素
arr.erase( std::remove_if( arr.begin(), arr.end(),
std::bind1st( std::less< int>(), 100)), arr.end());
这里的表达式相当于100 < arr.value
当然为了实现删除大于100的元素你同样可以使用bind2nd
// 移除所有大于100的元素
arr.erase( std::remove_if( arr.begin(), arr.end(),
std::bind2nd( std::greater< int>(), 100)), arr.end());
前面说道=的比较,比如说x <= k怎么实现呢,std又提供了一个好东西not1,
我们可以说 !(x > k) 和 x <= k是等价的,那么我们看看下面的表达式:
// 移除所有小于等于100的元素
arr.erase( std::remove_if( arr.begin(), arr.end(),
std::not1(std::bind2nd( std::greater< int>(), 100))), arr.end());
说明:not1是否定返回值是单目的函数,std中还有not2它是否定返回值是双目的函数
例子需要包含头文件
#include <vector>
#include <algorithm>
#include <functional>
一直对取反器和绑定器的行为感到困惑,这次将VC 6.0相关的代码抽取出来,
研究了一番,终于理解了个大概,not1和bind2nd都是模板函数,
它们的功能都是返回一个函数对象,具体的工作都是由函数对象来完成的。
测试代码如下(用g++通不过编译,用VC 6.0可以):
#include <iostream>
//#include <functional> //not1,bind2nd实现所在的头文件
#include <vector>
#include <algorithm>
using namespace std;
//binary_function,unary_function这两个结构体什么也没有 ,
//仅仅有几个typedef,这样的结构体在STL的实现中被大量用到
template<class _A1, class _A2, class _R>
struct binary_function {
typedef _A1 first_argument_type;
typedef _A2 second_argument_type;
typedef _R result_type;
};
template<class _A, class _R>
struct unary_function {
typedef _A argument_type;
typedef _R result_type;
};
//less类重载了函数运算符号,它没有任何属性,默认的构造函数什么也不会做
//正因为它没有相应的属性,所以需要绑定器来帮助它工作
//如果给less加上一个参数,那就不需要绑定器帮忙了
template<class _Ty>
struct less : binary_function<_Ty, _Ty, bool> {
bool operator()(const _Ty& _X, const _Ty& _Y) const
{return (_X < _Y); }
};
//我们这样实现一个自己的less类,可以和上面的实现比较一番
//显然STL标准实现less类是更加妥当的,less只是取到一个判断的作用
//它不应该包含判断用的数值
template<class _Ty>
struct myless
{
public:
myless(const _Ty& _X) : m_y(_X)
{
}
bool operator()(const _Ty& _X) const
{return (_X < m_y); }
private:
_Ty m_y;
};
private:
_Ty m_y;
};
//binder2nd类value属性保存了比较值,它重载的函数运算符函数将这个比较值
//和接受的参数一同送给less对象处理,然后返回其判断结果
template<class _Bfn>
class binder2nd : public unary_function<_Bfn::first_argument_type, _Bfn::result_type>
{
public:
binder2nd(const _Bfn& _X, const _Bfn::second_argument_type& _Y) : op(_X), value(_Y) {}
result_type operator()(const argument_type& _X) const
{return (op(_X, value)); }
protected:
_Bfn op;
_Bfn::second_argument_type value;
};
//bind2nd是一个模板函数,它返回一个bind2nd函数对象
//可以看出来第一个实例化参数_Bfn必须从binary_function派生
//否则它不会有second_argument_type,less结构体便是从
//binary_function派生的
template<class _Bfn, class _Ty> inline
binder2nd<_Bfn> bind2nd(const _Bfn& _X, const _Ty& _Y)
{
return (binder2nd<_Bfn>(_X, _Bfn::second_argument_type(_Y)));
}
//unary_negate类简单地将_Fn(_X)取反
template<class _Ufn>
class unary_negate : public unary_function<_Ufn::argument_type, bool>
{
public:
explicit unary_negate(const _Ufn& _X) : _Fn(_X) {}
bool operator()(const _Ufn::argument_type& _X) const
{
return (!_Fn(_X));
}
protected:
_Ufn _Fn;
};
//not1也是一个模板函数
//它返回一个unary_negate函数对象
template<class _Ufn> inline
unary_negate<_Ufn> not1(const _Ufn& _X)
{
return (unary_negate<_Ufn>(_X));
}
int main()
{
vector<int> vec;
vec.push_back(4);
vec.push_back(7);
vec.push_back(5);
//下面两句的的作用是一样的,bind2nd可以被默认实例化
//vector<int>::iterator iter = find_if(vec.begin(), vec.end(), bind2nd(less<int>(), 5));
vector<int>::iterator iter = find_if(vec.begin(), vec.end(),
bind2nd<less<int>, int>(less<int>(), 5));
//使用我们自己实现的myless类
myless<int> my(5);
//这里就不需要使用绑定器了
vector<int>::iterator iter = find_if(vec.begin(), vec.end(), my);
cout << *iter << endl; //结果为4
return 0;
}
find_if(vec.begin(), vec.end(),
bind2nd<less<int>, int>(less<int>(), 5));
这个函数的含义是,对vec中的每一项,调用bind2nd对象的operator() 函数,相当于:
bind2nd<less<int>, int>(less<int>(), 5).operator()( *itr )
bind2nd<less<int>, int>(less<int>(), 5) 是一个binder2nd 类的对象,它
的模板参数有两个,一个是less<int>类,一个是int类型, 这个对象的构造函数有两个
参数,一个是less<int>类的临时对象,一个是int 5。
构造函数中初始化 less<int> 类的成员变量op和 类成员变量 value,op初始化为
临时对象less<int>(), value初始化为5;
bind2nd<less<int>, int>(less<int>(), 5).operator()( *itr )
相当于调用:
op( *itr, vallue ); 也就是 less<int> ( *itr, 5 );
要求第一个参数类型 为继承自binary_function的类,也就是这里的less<int> 类