1 bind的作用
bind函数可以看作一个通用的函数适配器,接受一个可调用对象,生成一个新的可调用对象。
一般调用形式为
auto newCallable = bind(callable, arg_list)
当callable是类的成员函数时,调用方式会有变化,不但需要传入成员函数,还需要传入对象的指针,参考下面的例子
#include <functional>
#include <string>
#include <iostream>
void goodbye(const std::string& s){
std::cout << "Goodbye " << s << '\n';}
class Object {
public:
void hello(const std::string& s){
std::cout << "Hello " << s << '\n';}
};
int main(int argc, char* argv[]){
typedef std::function<void(const std::string&)> ExampleFunction;
Object instance;
std::string str("World");
ExampleFunction f = std::bind(&Object::hello, &instance, std::placeholders::_1);
// 等价于 instance.hello(str)
f(str);
f = std::bind(&goodbye, std::placeholders::_1);
// 等价于 goodbye(str)
f(str);
return 0;
}
其中,newCallble本身是一个可调用对象,arg_list 是一个逗号分割的参数列表,对应给定的callable的参数。
当我们调用newCallable时,newCallable会调用callable,并传递给它arg_list中的参数。
arg_list中的参数可能包含形如_n的名字,其中n是一个整数,这些参数是“占位符” ,表示newCallable的参数,他们占据了newCallable的参数的位置,数值n表示生成的可调用对象中的参数的位置,
_1: 表示newCallable中的第一个参数
_2: 表示newCallable中的第二个参数
可以用bind修正参数的值,更一般的是,可以用bind绑定给定可调用对象中的参数或重新安排其顺序。
例如,加入f是一个可调用对象,它有5个参数,则下面对bind的调用,
auto g = bind(f,a,b,_2,c,_1);
会生成一个新的可调用对象,它有两个参数,分别用占位符_2,_1表示,这个新的可调用对象将它自己的参数作为第三个和第五个参数传递给f。 f的第一个,第二个,第四个参数分别被绑定到给定的a,b,c上。
实际上,这个bind调用会将g(_1,_2)映射为f(a,b,_2,c,_1)
调用
g(X,Y)等价与调用 f(a,b,Y,c,X)
2 标准库funtion类型
funtion定义在functional头文件中,function是一个模板,当创建一个具体的function类型时,需要提供额外的信息,指的是function类型能够表示的对象的调用形式。
在一对尖括号内指定类型
funtion<int(int, int)> 就声明了一个function类型,它可以接受两个int,返回一个int的可调用对象。
使用方式:
function<int(int,int)> f1 = add; // 传递函数指针
function<int(int,int)> f2 = divide(); // 传递函数对象类的对象
function<int(int,int)> f3 = [](int i, int j) {return i * j) //传递lambda函数
3 palceholder
std::placeholders 命名空间含有占位对象 [_1, . . . _N] ,其中 N 是实现定义的最大数字。
在std::bind 表达式用作参数时,占位符对象被存储于生成的函数对象,而以未绑定参数调用函数对象时,每个占位符 _N 被对应的第 N 个未绑定参数替换。