bind
概念
- boost中的bind是bind1st/bind2nd的增强版,它也会返回一个函数对象,可以通过function来保存和调用。
- bind()的第一个参数必须是一个可调用对象,比如函数、函数指针、函数对象,之后它最多接受九个参数。
- 占位符用来表示使用哪一个参数。boost中的bind位于头文件"boost/bind.hpp"中,
- c++11中已经增加了bind,头文件为,使用占位符的话需要其所在的命名空间:using namespace std::placeholders;
使用
绑定普通函数
#include <iostream>
using namespace std;
#include "boost/bind.hpp"
#include "boost\function.hpp"
void func1p(int num)
{
cout << num << endl;
}
void func3p(int a, int b, int c)
{
cout << a << endl << b << endl << c << endl;
}
int main()
{
int n = -1;
//绑定变量n到func1p的参数:不用再传参;
boost::function<void()> fun = boost::bind(func1p, n);
fun(); //输出-1
int x = 0, y = 5, z = 10;
//绑定变量x到func3p的第一个参数:第一个参数直接使用x,不用传参;第二个参数使用实参列表的第一个参数;第三个参数使用实参列表的第二个参数
boost::function<void(int, int)> func = boost::bind(func3p, x, _1, _2);
func(y, z); //输出0, 5, 10
//绑定变量y到func3p的第二个参数:第二个参数直接使用y,不用传参;第一个参数使用实参列表的第一个参数;第三个参数使用实参列表的第二个参数
func = boost::bind(func3p, _1, y, _2);
func(x, z); //输出0, 5, 10
//绑定变量z到func3p的第三个参数:第三个参数直接使用z,不用传参;第一个参数使用实参列表的第一个参数;第二个参数使用实参列表的第二个参数
func = boost::bind(func3p, _1, _2, z);
func(x, y); //输出0, 5, 10
return 0;
}
#include "boost/bind.hpp"
bool ShorterThanFun(const string& str, int len)
{
return str.length() < len;
}
int main()
{
vector<string> myVector = list_of("c++") ("c#") ("python");
int len = 5;
int count = count_if(myVector.begin(), myVector.end(), bind(ShorterThanFun, _1, len));
return 0;
}
绑定类的成员函数
#include "boost/bind.hpp"
class CMyClass
{
public:
void print()
{
cout << m_Value1 << ", " << m_Value2 << endl;
}
private:
int m_Value1 = 0, m_Value2 = 0;
};
void Print(CMyClass& c)
{
c.print();
}
int main()
{
vector<CMyClass> v(10);
for_each(v.begin(), v.end(), /*Print*/boost::bind(&CMyClass::print, _1));
return 0;
}
绑定类的成员变量
#include "boost/bind.hpp"
class CPoint
{
public:
int x = -1;
int y = -1;
};
int assign(CPoint point)
{
return point.x;
}
int main()
{
vector<CPoint> inputV(10);
vector<int> outputV(10);
transform(inputV.begin(), inputV.end(), outputV.begin(),
/*assign*/bind(&CPoint::x, _1) );
for (auto iter = outputV.begin(); iter != outputV.end(); iter++)
cout << *iter << endl;
return 0;
}
绑定函数对象
- 下面为使用count_if()算法来查找容器中元素长度小于5的个数,而count_if()使用的仿函数类型中只有一个参数,可以使用两种方法来实现长度参数的传递:
- 一种是将长度作为仿函数的构造函数的参数传入,
- 一种是使用bind来获得一个参数的仿函数:
#include "boost/bind.hpp"
class CLengthShorterThan
{
public:
CLengthShorterThan(int len):m_len(len){}
bool operator()(const string& str)
{
return str.length() < m_len;
}
private:
int m_len;
};
class CLenShorterThan
{
public:
bool operator() (const string& str, int len)
{
return str.length() < len;
}
typedef bool result_type;
};
int main()
{
vector<string> myVector = list_of("c++") ("c#") ("python");
int len = 5;
int count = count_if(myVector.begin(), myVector.end(), /*CLengthShorterThan(len)*/bind(CLenShorterThan(), _1, len));
return 0;
}
bind配合使用ref
- bind采用拷贝的方式存储绑定的对象或参数,
- 如下为使用count_if()算法来获得容器中元素长度小于5的元素个数,bind绑定len到仿函数的第二个参数,len参数是值传递,即使在operator()中被声明为了int&:
- 可以给bind绑定的参数传入ref()引用包装类型,使参数为引用传递:
#include "boost/bind.hpp"
class CLenShorterThan
{
public:
bool operator() (const string& str, int& len)
{
int iLen = len;
len = 0;
return str.length() < iLen;
}
typedef bool result_type;
};
int main()
{
vector<string> myVector = list_of("c++") ("c#") ("python");
int len = 5;
int count = count_if(myVector.begin(), myVector.end(),
bind(CLenShorterThan(), _1, ref(len)));
cout << len << endl; //输出为0
return 0;
}
使用shared_ptr做线程参数
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <string>
using namespace std;
class A
{
public:
virtual void out() {cout << "A::out();" << endl;}
};
class B : public A
{
public:
B() {cout << "construct B;" << endl;}
virtual void out() { cout << "B::out();" << endl; }
~B(){ cout << "destroy B;" << endl;}
};
/*
fun2 可以接收任何A类以及从A派生的类的shared_ptr对象.
这样做,勉强也可算是支持任意类型了,因为只要传递的参数是从A派生即可.
*/
void* fun2(boost::shared_ptr<A> pa)
{
// 不再需要任何转换,直接访问其子类的虚方法了.
pa->out();
sleep(10);
}
void fun()
{
/*
代码确实很简洁了.
*/
boost::shared_ptr<B> pb(new B());
boost::thread bthread(boost::bind(fun2, pb));
bthread.join();
}
int main()
{
fun();
cout << "FINISH" << endl;
}