bind - boost

头文件: boost/bind.hpp

bind 是一组重载的函数模板.
用来向一个函数(或函数对象)绑定某些参数. 
bind的返回值是一个函数对象.

它的源文件太长了. 看不下去. 这里只记下它的用法:

9.1 对于普通函数

假如有函数 fun() 如下: 
 void fun(int x, int y) {
  cout << x << ", " << y << endl;
 }
现在我们看看怎么用bind 向其绑定参数. 
对于像 fun 这样的普通函数. 若fun 有n个参数. 则 bind 需要 n+1 个参数: 原始函数的地址 以及 n个要绑定的参数.

第1种用法: 
向原始函数 fun 绑定所有的参数
 boost::bind(&fun, 3, 4)     // bind的实参表依次为: 要绑定的函数的地址, 绑定到fun的第一个参数值, 第二个参数值...
        // fun有多少个参数, 这里就要提供多少个.
表示将 3 和 4 作为参数绑定到 fun 函数. 
因为绑定了所有的参数. 现在我们调用bind所返回的函数对象:
 boost::bind(&fun, 3, 4)( );  //无参数. 
就会输出 3, 4

第2种用法: 
向原始函数 fun 绑定一部分参数
 boost::bind(&fun, 3, _1)    // bind的实参表依次还是: 要绑定的函数的地址, 要绑定到fun的第一个参数值, 然后注意
        // 因为我们不打算向fun绑定第2个参数(即我们希望在调用返回的Functor时再指定这个参数的值)
        // 所以这里使用 _1 来占位. 这里的 _1 代表该新函数对象被调用时. 实参表的第1个参数.
        // 同理下边还会用到 _2 _3 这样的占位符. 
这里只为fun绑定了第一个参数3. 所以在调用bind返回的函数对象时. 需要:
 boost::bind(&fun, 3, _1)(4);  //这个4 会代替 _1 占位符.
输出 3, 4
同理 boost::bind(&fun, _1, 3)(4); 
输出 4, 3

第3种用法:
不向 fun 绑定任何参数
 boost::bind(&fun, _1, _2)   // _1 _2 都是占位符. 上边已经说过了.
所以它就是 将新函数对象在调用时的实参表的第1个参数和第2个参数 绑定到fun函数.  
 boost::bind(&fun, _1, _2)(3, 4);    // 3将代替_1占位符, 4将代替_2占位符.
输出 3, 4
同理 boost::bind(&fun, _2, _1)(3, 4);   // 3将代替_1占位符, 4将代替_2占位符.
会输出 4, 3  
同理 boost::bind(&fun, _1, _1)(3);     // 3将代替_1占位符
会输出 3, 3

对于普通函数就这些. 对于函数对象. 如:
 struct Func {
  void operator()(int x) {
   cout << x << endl;
  }
 } f;
绑定的时候可能要指出返回值的类型:
 boost::bind<void>(f, 3)();  //指出返回值的类型 void

9.2 对于非静态成员函数

假如有:
 struct A {
  void func(int x, int y) {
   cout << x << "," << y << endl;
  }
 };
 
 A a;  
 A* pa = new A; //指针
 boost::shared_ptr<A> ptr_a(pa);  //智能指针.
 
现在要向像 A::func 这样的非静态成员函数绑定. 
若A::func有n个参数, 则 bind 要有 n+2 个参数: 指向成员函数fun的指针, 绑定到this的对象, n个参数.
如:  
 boost::bind(&A::func, a, 3, 4)();    //输出 3, 4
 boost::bind(&A::func, pa, 3, 4)();   //输出 3, 4
 boost::bind(&A::func, ptr_a, 3, 4)();//输出 3, 4
同样可以用 _1 这样的占位符. 如:
 boost::bind(&A::func, _1, 3, 4)(ptr_a);//输出 3, 4

可以看出. 不论传递给bind 的第2个参数是 对象. 对象指针. 还是智能指针. bind函数都能够正常工作.

9.3 bind嵌套

有个类如下. 记录人的信息:
 class Personal_info {
  string name_;
  int age_;
 public:
  int get_age();
  string name();
 };

vector<Personal_info> vec; 
 ...
现在要对 vec 排序. 可以用 bind 函数做一个比较谓词
 std::sort(  
  vec.begin(),  
  vec.end(),  
  boost::bind( 
   std::less<int>(),    
   boost::bind(&personal_info::age,_1),     //_1 占位符是 sort 中调用比较函数时的第一个参数.
   boost::bind(&personal_info::age,_2)));   //_2 占位符是 sort 中调用比较函数时的第二个参数.

9.4 函数组合

假如有:
 vector<int> ints;
 ...
想用 std::count_if() 来求ints中有多少是 >5 且 <=10 的. 这在常规代码中通常就要写一个函数来实现这个谓词:
 if (i>5 && i<=10) ...
现在用bind则可以:
 std::count_if(  
  ints.begin(),  ints.end(),  
  boost::bind(    
   std::logical_and<bool>(),    
   boost::bind(std::greater<int>(),_1,5),    
   boost::bind(std::less_equal<int>(),_1,10)));

9.5 绑定到成员变量

有:
 map<int, string> my_map;
 my_map[0]="Boost";my_map[1]="Bind";
现在要输出所有元素的 second 成员. 也就是输出这些字符串. 其中的打印函数如下:
 void print_string(const string& s) {  
  std::cout << s << '/n';
 }
则可以:
 for_each(  
  my_map.begin(),  
  my_map.end(),  
  boost::bind(
   &print_string, 
   boost::bind(&std::map<int,std::string>::value_type::second,_1)
   )
  );
  
汗... 看不懂bind的源码. 也不知是如何实现这些功能的. 只能等<<boost源码剖析>>出来了.

注意:
(以下补于08年6月3日)

boost::bind() 返回的函数对象会保存要绑定的实参. 而且总是拷贝一份以值的方式保存..
这主要是考虑到被绑定的实参的生命期.  
但这并不总是我们期望的. 例如有时我们希望它保存指针或引用:

有函数:
void f(int & x) { ++x; }
然后:
int n = 0;
bind(&f, n)();    //我们希望 n==1 . 但实际上没有这样...

要避免这种对象复制.  而要bind得到的函数对象保存实参的引用语义. 可以:
使用 boost::ref()  或 boost::cref() 如
bind(&f, ref(n))();        //OK,  执行后 n==1

如果是绑定一个对象到它的成员函数上. 如:
A a;
bind(&A::fun, a);       //则保存的是 a对象的拷贝.
要避免这种拷贝. 除了上面提到的 ref() 外, 也可以:
bind(&A::fun, &a);      //用指针.  反正用对象和用指针都可以. 而用指针可以避免对象拷贝的问题.

注意: (以下补于6月10日)
bind () 的第一个参数——被绑定函数——是不被求值的. 如下例:

typedef void (*pf)(int);
std::vector<pf> v;  //v中有一些函数指针.
std::for_each(v.begin(), v.end(), bind(_1, 5));   //想实现 _1(5);  这样的调用. 但这样不行!

正确的做法是借助 boost::apply 模板(来自boost/bind/apply.hpp).  
apply也是一个函数对象. 它的作用如下:
apply<void> a;   //模板参数为函数对象的返回值类型.
a(x);       //相当于调用 x();
a(x, y);    //相当于调用  x(y);
a(x, y, z);  //相当于调用 x(y, z);
所以错误的bind应该写为:
std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5));

boost bind使用指南的更多相关文章

  1. C++ 系列:Boost Thread 编程指南

    转载自:http://www.cppblog.com/shaker/archive/2011/11/30/33583.html 作者: dozbC++ Boost Thread 编程指南0 前言1 创 ...

  2. 1,Boost -> Bind

    #include <boost/bind.hpp> #include <boost/shared_ptr.hpp> #include <iostream> usin ...

  3. boost::bind

    bind并不是一个单独的类或函数,而是非常庞大的家族,依据绑定的参数个数和要绑定的调用对象类型,总共有十个不同的形式,但它们的名字都叫bind. bind接受的第一个参数必须是一个可调用对象f,包括函 ...

  4. boost::bind 和 boost::function 基本用法

    这是一篇介绍bind和function用法的文章,起因是近来读陈硕的文章,提到用bind和function替代继承,于是就熟悉了下bind和function的用法,都是一些网上都有的知识,记录一下,期 ...

  5. 以boost::function和boost:bind取代虚函数

    转自:http://blog.csdn.net/Solstice/archive/2008/10/13/3066268.aspx 这是一篇比较情绪化的blog,中心思想是“继承就像一条贼船,上去就下不 ...

  6. (转)boost::bind介绍

    转自:http://www.cnblogs.com/sld666666/archive/2010/12/14/1905980.html 这篇文章介绍boost::bind()的用法, 文章的主要内容是 ...

  7. boost::bind实践2——来自《Beyond the C++ Standard Library ( An Introduction to Boost )》

    直接代码: 代码段1: #include <iostream> #include <string> #include <boost/bind/bind.hpp> c ...

  8. boost::bind实践

    第一部分源码为基础实践: /*Beyond the C++ Standard Library ( An Introduction to Boost )[CN].chm*/ /*bind的用法*/ #i ...

  9. 关于boost::function与boost::bind函数的使用心得

    最近开始写一个线程池,期间想用一个通用的函数模板来使得各个线程执行不同的任务,找到了Boost库中的function函数. Boost::function是一个函数包装器,也即一个函数模板,可以用来代 ...

随机推荐

  1. Linux测试上行和下载速率

    下载安装speedtest-cli测试工具 方法一: pip3 install speedtest-cli 方法二: wget https://github.com/sivel/speedtest-c ...

  2. Dapper 嵌套对象查询

    我有这样一个一对一关系的表结构:User->UserInfo User: /// <summary> /// 用户 /// </summary> [Serializabl ...

  3. linux系统编程之进程(七):system()函数使用

    一,system()理解 功能:system()函数调用"/bin/sh -c command"执行特定的命令,阻塞当前进程直到command命令执行完毕 原型: int syst ...

  4. JWT+ASP.NET MVC 时间戳防止重放攻击

     时间戳作用 客户端在向服务端接口进行请求,如果请求信息进行了加密处理,被第三方截取到请求包,可以使用该请求包进行重复请求操作.如果服务端不进行防重放攻击,就会服务器压力增大,而使用时间戳的方式可以解 ...

  5. pgAdmin4 汉化

  6. Win(Phone)10开发第(3)弹,简单的Demo程序网络请求json解析列表显示

    先分享一个由Json字符串直接生成解析对应的类的工具: jsonclassgenerator14 百度天气接口 下面是由一个小功能(又特么的是天气)的实现,记录下下UAP的流程和结构(其实跟之前一模一 ...

  7. UE4随笔(一)准备过程

    19号,也就是中国时间20日凌晨,虚幻4放出了"订阅制"这个重磅炸弹,估计出乎大多数人的想象,已经不止一个同事表示"自己的引擎这下没用了". 笔者前天搞定了付款 ...

  8. Struts2乱码问题的解决办法

    乱码问题的起因在于数据在web系统的各个层中间传递的时候编码不同,比如页面使用GB18030而中间层使用UTF-8.由于struts2默认使用的就是UTF-8编码,所以在页面如果使用的是其他的编码格式 ...

  9. Python 将时间戳转换为本地时间并进行格式化

    在python中,时间戳默认是为格林威治时间,而我们为东八区 使用localtime() 本地化时间戳 使用 strftime() 格式化时间戳 time = time.strftime('%Y%m% ...

  10. 【AUTO Uninstaller 中文版-详细使用教程】AUTODESK系列软件MAYA/CAD/3DSMAX/INVENTOR终极完美修复卸载工具 Windows x64位 【原创搬家】

    小伙伴是不是遇到 MAYA/CAD/3DSMAX/INVENTOR/REVIT 安装失败或者安装不了的问题了呢?AUTODESK系列软件着实令人头疼,MAYA/CAD/3DSMAX/INVENTOR/ ...