STL::bind1st STL::bind2st boost::bind

来源:互联网 发布:多态zpn mac 编辑:程序博客网 时间:2024/06/05 22:48

如果大家不了解了STL中的bind的话,可以先看一下下面的二中对STL:::bind1st的分析。通过对比我们就可以清楚的明白为什么要有boost了。

一、Boost.Bind 是这样的一个库,它简化了由C++标准中的 std::bind1st() 和   std::bind2nd()模板函数所提供的一个机制:将这些函数与几乎不限数量的参数一起使用,就可以得到指定签名的函数。    这种情形的一个最好的例子就是在C++标准中定义的多个不同算法。

#include <iostream>
#include <vector>
#include <algorithm>

void print(int i)
{
  std::cout << i << std::endl;
}

int main()
{
  std::vector<int> v;
  v.push_back(1);
  v.push_back(3);
  v.push_back(2);

  std::for_each(v.begin(), v.end(), print);
}

 

 

算法 std::for_each() 要求它的第三个参数是一个仅接受正好一个参数的函数或函数对象。    如果std::for_each() 被执行,指定容器中的所有元素 - 在上例中,这些元素的类型为   int - 将按顺序被传入至print() 函数。    但是,如果要使用一个具有不同签名的函数的话,事情就复杂了。 例如,如果要传入的是以下函数   add(),它要将一个常数值加至容器中的每个元素上,并显示结果。

void add(int i, int j)
{
  std::cout << i + j << std::endl;
}

由于 std::for_each() 要求的是仅接受一个参数的函数,所以不能直接传入    add() 函数。

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

class add
  : public std::binary_function<int, int, void>
{
public:
  void operator()(int i, int j) const
  {
    std::cout << i + j << std::endl;
  }
};

int main()
{
  std::vector<int> v;
  v.push_back(1);
  v.push_back(3);
  v.push_back(2);

  std::for_each(v.begin(), v.end(), std::bind1st(add(), 10));
}

以上程序将值10加至容器 v 的每个元素之上,并使用标准输出流显示结果。    源代码必须作出大幅的修改,以实现此功能:add() 函数已被转换为一个派生自   std::binary_function 的函数对象。如果我们不修改add为函数对象的话而直接将add()自由函数传给bind1st,编译器将会报错:/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/backward/binders.h:在‘std::binde
r1st<void(int, int)>’的实例化中:
boostBindExample.cpp:29:55:从此处实例化
/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/backward/binders.h:101:5: 错误:‘
void(int, int)’不是类、结构或联合类型

具体为什么会这样的错,如果不明白可以参看下面的二中对STL中的bind的介绍。

Boost.Bind 简化了不同函数之间的绑定。 它只包含一个 boost::bind()模板函数,定义于boost/bind.hpp 中。    使用这个函数,可以如下实现以上例子:

#include <boost/bind.hpp>
#include <iostream>
#include <vector>
#include <algorithm>

void add(int i, int j)
{
  std::cout << i + j << std::endl;
}

int main()
{
  std::vector<int> v;
  v.push_back(1);
  v.push_back(3);
  v.push_back(2);

  std::for_each(v.begin(), v.end(), boost::bind(add, 10, _1));
}

 

add() 这样的函数不再需要为了要用于    std::for_each() 而转换为函数对象。 使用    boost::bind(),这个函数可以忽略其第一个参数而使用。

因为 add() 函数要求两个参数,两个参数都必须传递给    boost::bind()。 第一个参数是常数值10,而第二个参数则是一个怪异的    _1

对于boost::bind()中的参数的使用,我们可以参看下面的例子:

#include <boost/bind.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;
void add(int i, int j)
{
std::cout << i + j << std::endl;
}
bool compare(int i, int j)
{
return i > j;
}
void printVector(vector<int> &v)
{
for(vector<int>::iterator i = v.begin(); i != v.end(); i++)
  cout << *i << " " ;
cout << endl;
}
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);

//std::for_each(v.begin(), v.end(), std::bind1st(add,10));

std::cout << "Follow bind add for for_each" << std::endl;
std::for_each(v.begin(), v.end(), boost::bind(add,19,_1));

cout << "Follow bind compare for sort that form big to little" << endl;
sort(v.begin(), v.end(), boost::bind(compare,_1,_2));
printVector(v);

cout << "Follow direct pass compare to sort" << endl;
sort(v.begin(), v.end(), compare);
printVector(v);

cout << "Follow bind compare for sort but form little to big" << endl;
sort(v.begin(), v.end(), boost::bind(compare,_2,_1));
printVector(v);
return 0;
}

==================================================

二、我们分析一下STL中的bind1st,通过对比我们可以看出boost::bind的优势。下面是STL中的bind1st的实现。通过分析下面的代码我们可以清楚的明白STL中的bind1st只能bind一个参数,且bind的是第一个参数。同样的bing2st只能bind第二个参数

template <class _Operation>
   class binder1st
   : public unary_function<typename _Operation::second_argument_type,           //大家请注意_Operation::second_argument_type,从这里可以看出如果是自由函数的

                                                                                                                                                 //话,在这里将会出错的.因为他不是::的前面不是类或struct
               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); }

     // _GLIBCXX_RESOLVE_LIB_DEFECTS
     // 109.  Missing binders for non-const sequence elements
     typename _Operation::result_type
     operator()(typename _Operation::second_argument_type& __x) const
     { return op(value, __x); }
   };

这里引用一下其他的例子:

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());

写到这里大家应该STL中的bind的用法了吧

原创粉丝点击