C++ Programmer's Cookbook

{C++ 基础} {C++ 高级} {C#界面,C++核心算法} {设计模式} {C#基础}

引领boost(六)(boost::bind)

 

Boost::bind


一 Boost::bind
   
   在STL中,我们经常需要使用bind1st,bind2st函数绑定器和fun_ptr,mem_fun等函数适配器,这些函数绑定器和函数适配器使用起来比较麻

烦,需要根据是全局函数还是类的成员函数,是一个参数还是多个参数等做出不同的选择,而且有些情况使用STL提供的不能满足要求,所以如

果可以我们最好使用boost提供的bind,它提供了统一的接口,提供了更多的支持,比如说它增加了shared_ptr,虚函数,类成员的绑定。

二 源码剖析

 1) bind1st,bind2st函数绑定器,把二元函数对象变为一元函数对象。
 2) mem_fun,把成员函数变为函数对象。
 3) fun_ptr,把一般的全局函数变为函数对象。
 4) boost::bind(),包含了以上所有的功能。


三 实例

 1)区别与mem_fun和fun_ptr

#include <functional>
#include 
<iostream>
#include 
<string>
#include 
"boost/bind.hpp"
class some_class 
{
public:      
    
void print_string(const std::string& s) const
    
{    
        std::cout 
<< s << '\n'
    }

    
void print_classname()
    
{
        std::cout 
<< "some_class" << std::endl;
    }

}
;
void print_string(const std::string s) 
{  std::cout << s << '\n';
}

void print_functionname()
{
    std::cout 
<< "Print_functionname" <<std::endl;
}

int main() 
{  
    std::ptr_fun(
&print_string)("hello1");
    
//std::ptr_fun<void>(&print_functionname);
    some_class sc0;
    std::mem_fun_ref(
&some_class::print_classname)(sc0);
    std::mem_fun_ref
<void,some_class>(&some_class::print_classname)(sc0);
    
//std::mem_fun1_ref<void,some_class,const std::stirng>(&some_class::print_string)(sc0,"hello2");

    (boost::bind(
&print_string,_1))("Hello func!");  
    boost::bind(
&print_functionname);
    some_class sc;  
    (boost::bind(
&some_class::print_classname,_1)(sc));
    (boost::bind(
&some_class::print_string,_1,_2))(sc,"Hello member!");
}

 

 2)区别与bind1st和bind2st

#include <functional>
#include 
<iostream>
#include 
<string>
#include 
<vector>
#include 
<algorithm>
#include 
"boost/bind.hpp"
void main()
{
    std::vector
<int> ints;
    ints.push_back(
7);
    ints.push_back(
4);
    ints.push_back(
12);
    ints.push_back(
10);
    
int count=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))
        );
    std::cout 
<< count << '\n';
    std::vector
<int>::iterator int_it=std::find_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))
        );
    
if (int_it!=ints.end()) 
    
{  std::cout << *int_it << '\n';}

}

 

 3)区别传ref和传instance

// bind instance or reference
#include <functional>
#include 
<iostream>
#include 
<string>
#include 
<vector>
#include 
<algorithm>
#include 
"boost/bind.hpp"
class tracer 
{
public
    tracer() 
{    std::cout << "tracer::tracer()\n";  } 
    tracer(
const tracer& other) {    std::cout << "tracer::tracer(const tracer& other)\n";  } 
    tracer
& operator=(const tracer& other)
    
{    std::cout <<      "tracer& tracer::operator=(const tracer& other)\n";    return *this;  } 
    
~tracer() {    std::cout << "tracer::~tracer()\n"
    }
 
    
void print(const std::string& s) const
    
{    std::cout << s << '\n';  }
}
;

void main()
{
    tracer t;
    boost::bind(
&tracer::print,t,_1)(std::string("I'm called on a copy of t\n"));
    tracer t1;
    boost::bind(
&tracer::print,boost::ref(t1),_1)(  std::string("I'm called directly on t\n"));

}

 

 4)绑定虚函数

//bind vitual class function
#include <functional>
#include 
<iostream>
#include 
<string>
#include 
<vector>
#include 
<algorithm>
#include 
"boost/bind.hpp"
class base {
public:
    
virtual void print() const 
    
{    std::cout << "I am base.\n";  
    }
  
    
virtual ~base() {}
}
;
class derived : public base 
{
public
    
void print()const 
    
{    std::cout << "I am derived.\n";  }
}
;

void main()
{
    derived d;
    
base b;
    boost::bind(
&base::print,_1)(b);
    boost::bind(
&base::print,_1)(d);
}

 

 5)绑定成员变量

// bind class's member
#include <functional>
#include 
<iostream>
#include 
<string>
#include 
<vector>
#include 
<algorithm>
#include 
"boost/bind.hpp"
class personal_info 

    std::
string name_;  
    std::
string surname_;
    unsigned 
int age_;
public
    personal_info(
const std::string& n,const std::string& s,unsigned int age):name_(n),surname_(s),age_(age) {} 
    std::
string name() const {return name_;} 
    std::
string surname() const {return surname_;} 
    unsigned 
int age() const {return age_;}
}
;

void main()
{
 std::vector
<personal_info> vec;
 vec.push_back(personal_info(
"Little","John",30));
 vec.push_back(personal_info(
"Friar""Tuck",50));
 vec.push_back(personal_info(
"Robin""Hood",40));
 std::sort(vec.begin(),
     vec.end(),
     boost::bind(std::less
<unsigned int>(),boost::bind(&personal_info::age,_1),boost::bind(&personal_info::age,_2))
     );
 std::sort(vec.begin(),
     vec.end(),
     boost::bind(std::less
<std::string>(),boost::bind(&personal_info::surname,_1),boost::bind(&personal_info::surname,_2))
     );
}

 

四 注意

 1) 现在的类库最多可以支持9个参数。
 2)在绑定一个成员函数时,bind 表达式的第一个参数必须是成员函数所在类的实例!理解这个规则的最容易的方法是,这个显式的参数将取

替隐式的 this ,被传递给所有的非静态成员函数。细心的读者将会留意到,实际上这意味着对于成员函数的绑定器来说,只能支持八个参数

,因为第一个要用于传递实际的对象。
 3)当我们传递某种类型的实例给一个 bind 表达式时,它将被复制,除非我们显式地告诉 bind 不要复制它。要避免复制,我们必须告诉

bind 我们想传递引用而不是它所假定的传值。我们要用 boost::ref 和 boost::cref (分别用于引用和 const 引用)来做到这一点,它们也是

Boost.Bind 库的一部分。还有一种避免复制的方法;就是通过指针来传递参数而不是通过值来传递。
 4) 通过 Boost.Bind, 你可以象使用非虚拟函数一样使用虚拟函数,即把它绑定到最先声明该成员函数为虚拟的基类的那个虚拟函数上。这

个绑定器就可以用于所有的派生类。如果你绑定到其它派生类,你就限制了可以使用这个绑定器的类。
 5)bind还可以绑定成员变量。

五 参考

1)Beyond the C++ Standard Library: An Introduction to Boost
2)boost在线document

 

posted on 2007-09-05 14:40 梦在天涯 阅读(6278) 评论(4)  编辑 收藏 引用 所属分类: CPlusPlusSTL/Boost

评论

# re: 引领boost(六)(boost::bind) 2007-09-05 14:41 梦在天涯

在第一个sample代码中2行注释的代码有问题,谁能帮忙解决哦,请高手指点哦!  回复  更多评论   

# re: 引领boost(六)(boost::bind) 2007-09-05 16:52 蚂蚁终结者

//std::ptr_fun<void>(&print_functionname);
std::ptr_fun返回的是unary function 或 binary function,不能用于无参函数,实际上也没必要。

//std::mem_fun1_ref<void,some_class,const std::stirng>(&some_class::print_string)(sc0,"hello2");
如果你用的是Macrosoft的STL,std::mem_fun1_ref会有bug,即只能用于非const成员函数,如果把some_class中的
void print_string(const string& s) const
改为
void print_string(const string& s)

然后再这样写就可以了:
std::mem_fun1_ref(&some_class::print_string)(sc0, "hello2");

当然了,用SGI的STL不会有这个bug
最好的办法是用std::mem_fun_ref,std::mem_fun_ref可用于一个参数或零个参数的const或non-const成员函数,std::mem_fun1_ref只能用于一个参数的const或non-const成员函数,估计是为了兼容性。
所以也可以这样写:
std::mem_fun_ref(&some_class::print_string)(sc0, "hello2");
这样print_string加不加const都一样
  回复  更多评论   

# re: 引领boost(六)(boost::bind) 2007-09-05 17:01 梦在天涯

蚂蚁终结者说的是正确的

std::mem_fun_ref(&some_class::print_string)(sc0,"hello2");
是正确的!(主要是我一开始以为它只能用于无参数函数的情况,看来是错误的,可以用于有一个参数的函数)

//std::ptr_fun<void>(&print_functionname);
这个可能也想蚂蚁终结者说的,没有什么必要!

不知道stl里有没有提供更多参数的支持!  回复  更多评论   

# re: 引领boost(六)(boost::bind) 2007-09-27 18:28 沐枫

@梦在天涯
有更多的参数支持。但默认只支持10个以内。
需要更多的参数,要修改源代码中的一个宏定义。我以前曾看过,代码中有50个以内的参数定义预留。
  回复  更多评论   


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

EMail:itech001#126.com

导航

统计

  • 随笔 - 461
  • 文章 - 4
  • 评论 - 746
  • 引用 - 0

常用链接

随笔分类

随笔档案

收藏夹

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

积分与排名

  • 积分 - 1654455
  • 排名 - 5

最新评论

阅读排行榜