bind是什么
bind是一个标准库函数,定义在functional头文件中。可以将bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成新的可调用对象来适应原对象的参数列表。
bind怎么用
调用bind的一般形式为:
auto newCallable=bind(callable,arg_list);
newCallable和callable都是可调用对象,arg_list对应calllable的参数。当我们调用newCallable时,newCallable会调用callable,并传递给它arg_list中的参数
arg_list中的参数可能包含形如_n的占位符,如_1,_2,代表了newCallable中相应位置的参数
auto check6=bind(check_size,_1,6);
当我们调用check6(str)的时候,实际会调用check_size(str,6)
bind作用
改变参数个数
bind可以用于改变参数的个数(减少?),如原本check_size要传入两个参数,通过bind我们可以只传入一个参数,另外的参数则在bind时决定。
改变参数位置
bind还可用于改变参数位置,例如,有一个函数bool isGreater(int a,int b)用于判断第一个参数是否大于第二个参数,则
auto isSmaller=bind(isGreater,_2,_1);
通过改变参数顺序,让bind返回的可调用对象具有相反的含义。isSmaller(1,2)将实际调用isGreater(2,1),返回true。
设置类成员函数为回调函数
回调函数往往通过函数指针来实现,而类的成员函数,多了一个隐含的参数this,所以直接赋值给函数指针会引起编译报错。通过bind可以解决此问题
class MyClass
{
public:
MyClass() :n(0) {};
~MyClass()=default;
void add(int i) { n += i; cout << n; }
private:
int n;
};
MyClass a;
auto f=bind(&test::incr,&a,_1);
MyClass a;
auto f = bind(&MyClass::add, &a, _1);
f(1);//输出1
f(2);//输出 3
bind绑定引用参数
默认情况下,bind的那些不是占位符的参数被拷贝到bind返回的可调用对象中,但有些参数无法拷贝,可以使用标准库中的ref函数,它返回给定参数的引用。
例子:
ostream& print(ostream& os, const string& s, char c)
{
return os << s << c;
}
print(cout, "123", '-');//打印123-
//
vector<string> strVec = {"abc","def"};
//for_each(strVec.begin(), strVec.end(), bind(print,cout,_1,'-'));将报错cout无法拷贝
for_each(strVec.begin(), strVec.end(), bind(print,ref(cout),_1,'-'));//输出abc-def-