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