bind包装器
bind包装器介绍
bind也是一种函数包装器 也叫做适配器 它可以接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表 C++中的bind本质是一个函数模板
它的函数模板原型如下
template <class Fn, class... Args> /* unspecified */ bind(Fn&& fn, Args&&... args); template <class Ret, class Fn, class... Args> /* unspecified */ bind(Fn&& fn, Args&&... args);
其中各个参数的解释如下
- fn:可调用对象
- args…:要绑定的参数列表:值或占位符
使用格式如下
调用bind的一般形式为:auto newCallable = bind(callable, arg_list);
解释下各个标识符
- callable:需要包装的可调用对象
- newCallable:生成的新的可调用对象
- arg_list:逗号分隔的参数列表 对应给定的callable的参数 当调用newCallable时 newCallable会调用callable 并传给它arg_list中的参数。
rg_list中的参数可能包含形如_n的名字,其中n是一个整数,这些参数是“占位符”,表示newCallable的参数,它们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对象中参数的位置,比如_1为newCallable的第一个参数,_2为第二个参数,以此类推。
此外 除了用auto接收包装后的可调用对象 也可以用function类型指明返回值和形参类型后接收包装后的可调用对象
bind包装器绑定固定参数
无意义的绑定
下面的这次绑定就是无意义的绑定
int Plus(int x, int y) { return x + y; } int main() { auto newfunc = bind(Plus, placeholders::_1, placeholders::_2); // 也可以写成 //function<int(int,int)> newfunc= bind(Plus, placeholders::_1, placeholders::_2); cout << newfunc(1, 2); return 0; }
为什么说这是无意义包装呢
- 绑定时第一个参数传入函数指针这个可调用对象 但后续传入的要绑定的参数列表依次是placeholders::_1和placeholders::_2
- 也就是说第一个参数传递给了placeholders::_1 第二个参数传递给了placeholders::_2
- 综上 包装后的对象除了改了个名字之外什么功能都没有变 所以说这是无意义包装
绑定固定参数
比如说我们想完成一个函数 这个函数永远都是计算和10相加的值
那么这个时候我们就可以对于Plus函数进行包装
auto newfunc = bind(Plus, 10, placeholders::_1); cout << newfunc(12) << endl; cout << newfunc(1) << endl; cout << newfunc(2) << endl;
- 我们这里对于Plus包装的手法是将一个参数用常数代替
- 这也能说明bind包装器的底层原理其实就是替换参数
- 常数和占位符替换位置也是可以的
bind包装器调整参数顺序
其实知道了占位符中的placeholders::_n和参数传递的顺序有关系我们就能很简单的推断出如何修改bind包装器的参数顺序
int Sub(int x, int y) { return x - y; } int main() { auto newsub = bind(Sub, placeholders::_2, placeholders::_1); cout << Sub(10, 2) << endl; cout << newsub(10, 2); return 0; }
- 根据参数的传入顺序逆序placeholders即可
- 这再次证明了bind包装器是通过改变参数顺序来改变函数的
演示结果如下
bind包装器的意义
- 将一个函数的某些参数绑定为固定的值 让我们在调用时可以不用传递某些参数
- 可以对函数参数的顺序进行灵活调整