Boost::bind
一 Boost::bind
在STL中,我們經(jīng)常需要使用bind1st,bind2st函數(shù)綁定器和fun_ptr,mem_fun等函數(shù)適配器,這些函數(shù)綁定器和函數(shù)適配器使用起來比較麻
煩,需要根據(jù)是全局函數(shù)還是類的成員函數(shù),是一個參數(shù)還是多個參數(shù)等做出不同的選擇,而且有些情況使用STL提供的不能滿足要求,所以如
果可以我們最好使用boost提供的bind,它提供了統(tǒng)一的接口,提供了更多的支持,比如說它增加了shared_ptr,虛函數(shù),類成員的綁定。
二 源碼剖析
1) bind1st,bind2st函數(shù)綁定器,把二元函數(shù)對象變?yōu)橐辉瘮?shù)對象。
2) mem_fun,把成員函數(shù)變?yōu)楹瘮?shù)對象。
3) fun_ptr,把一般的全局函數(shù)變?yōu)楹瘮?shù)對象。
4) boost::bind(),包含了以上所有的功能。
三 實例
1)區(qū)別與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)區(qū)別與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)區(qū)別傳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)綁定虛函數(shù)
//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) 現(xiàn)在的類庫最多可以支持9個參數(shù)。
2)在綁定一個成員函數(shù)時,bind 表達式的第一個參數(shù)必須是成員函數(shù)所在類的實例!理解這個規(guī)則的最容易的方法是,這個顯式的參數(shù)將取
替隱式的 this ,被傳遞給所有的非靜態(tài)成員函數(shù)。細心的讀者將會留意到,實際上這意味著對于成員函數(shù)的綁定器來說,只能支持八個參數(shù)
,因為第一個要用于傳遞實際的對象。
3)當我們傳遞某種類型的實例給一個 bind 表達式時,它將被復制,除非我們顯式地告訴 bind 不要復制它。要避免復制,我們必須告訴
bind 我們想傳遞引用而不是它所假定的傳值。我們要用 boost::ref 和 boost::cref (分別用于引用和 const 引用)來做到這一點,它們也是
Boost.Bind 庫的一部分。還有一種避免復制的方法;就是通過指針來傳遞參數(shù)而不是通過值來傳遞。
4) 通過 Boost.Bind, 你可以象使用非虛擬函數(shù)一樣使用虛擬函數(shù),即把它綁定到最先聲明該成員函數(shù)為虛擬的基類的那個虛擬函數(shù)上。這
個綁定器就可以用于所有的派生類。如果你綁定到其它派生類,你就限制了可以使用這個綁定器的類。
5)bind還可以綁定成員變量。
五 參考
1)Beyond the C++ Standard Library: An Introduction to Boost
2)boost在線document