boost bind 用法

来源:互联网 发布:关键词搜索软件 编辑:程序博客网 时间:2024/06/15 14:11

boost::bind()用来将一个函数或函数对象绑定某些参数,返回值是一个函数对象。

它提供一个任意的函数对象(仿函数)、函数、函数指针、成员函数指针。

上代码:

#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)); }
上述代码中bind绑定了一个一元函数对象。

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

_1 被称为占位符(placeholder),定义于 Boost.Bind。 除了 _1,Boost.Bind 还定义了_2_3对于 _1, boost::bind() 返回一个一元函数,即有且只有一个参数。

    当这个程序执行时,std::for_each() 对容器 v 中的每一个元素调用该一元函数。 元素的值通过占位符_1 传入到一元函数中。 这个占位符和常数值被进一步传递到add() 函数。 通过使用这种机制,std::for_each() 只看到了由boost::bind() 所定义的一元函数。 而boost::bind() 本身则只是调用了另一个函数,并将常数值或占位符作为参数传入给它。有点罗嗦。

    上述代码有点别扭,对每个元素加10,为什么不是两个参数呢?因为std::for_each() 要求一个一元函数作为其第三个参数。

下面看bind的二元函数用法:

#include <boost/bind.hpp>#include <vector>#include <algorithm>#include <iostream>bool compare(int i, int j){  return i > j;}int main(){  std::vector<int> v{1, 3, 2};  std::sort(v.begin(), v.end(), boost::bind(compare, _1, _2));  for (int i : v)    std::cout << i << '\n';}
    std::sort() 算法以容器 v 的两个元素来调用该函数,并根据返回值来对容器进行排序。如果compare()为true则swap(),容器将被按降序排列。但是,由于compare() 本身就是一个二元函数,所以使用 boost::bind() 确是多余的。可以直接这么写:

    std::sort(v.begin(), v.end(), compare);
不过用bind可以方便的反向排序:

std::sort(v.begin(), v.end(), boost::bind(compare, _2, _1));
只改变占位符的位置。但是这种先2后1的传参方式还是不用为好。


那么问题来了,看下面的代码—— boost::bind是怎么区分类成员函数和全局函数的?

class ClassA {public:         void test(int, int){}}  void mytest(ClassA* pObj, int, int) {}  typedef boost::function<void (int, int)> func;func f1 = boost::bind(ClassA::test, this, _1, _2);func f2 = boost::bind(mytest, pObj, _1, _2); 

关于bind的内部原理,
下面的示例程序说明了一切:

#include <stdio.h>  template<typename... ARGS>void bind(void (*func)(ARGS...), ARGS... args){   printf("plain function\n");   func(args...); // std::forward<> 从略。}  template<typename CLASS, typename... ARGS>void bind(void (CLASS::*func)(ARGS...), CLASS* clz, ARGS... args){   printf("member function\n");   (clz->*func)(args...);}  template<typename CLASS, typename... ARGS>void bind(void (CLASS::*func)(ARGS...) const, const CLASS* clz, ARGS... args){   printf("const member function\n");   (clz->*func)(args...);}  void foo(int arg){   printf("foo %d\n", arg);}  class Bar{  public:   void write(double arg)   {     printf("Bar::write %f\n", arg);   }     void read(long arg) const   {     printf("Bar::read %ld\n", arg);   }};  void zoo(Bar* x){   printf("zoo %p\n", x);}  int main(){   bind(foo, 123);   Bar bar;   bind(&Bar::write, &bar, 3.14);   bind(&Bar::read, &bar, 42L);   bind(zoo, &bar);} 

这是Partial Template Specialization技术,即模板的"偏特化"或叫"部分特化"。










0 0