文章目录
- 1.介绍
- 头文件
- 定义
- 原型
- 2.引入
- 2.1现有语法无法解决
- 2.2bind的文档阅读
- 2.3bind()绑定函数对于2.1问题的解决
1.介绍
头文件
#include <functional>
定义
bind函数定义在头文件中,是一个函数模板,它就像一个函数包装器(适配器),接收一个可调用对象(callable object),生成一个新的可调用对象来==“适应”原对象的参数列表==。用它可以把一个原本接收N个参数的函数fn,通过绑定一些参数,返回一个接收M个(M可以大于N,但这么做没什么意义)参数的新函数。同时,使用bind函数还可以实现参数顺序调整等操作。
简而言之
bind函数用于把已知函数与某种参数与进行绑定,形成新的函数。
什么叫做绑定?
更改已知函数调用模式
如何理解bind?
可以将bind函数看作是一个通用的函数适配器,接收一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。调用bind的一般形式:auto newCallable = bind(callable,arg_list);
其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中的参数。
arg_list中的参数可能包含形如_n的名字,其中n是一个整数,这些参数是“占位符”,表示
newCallable的参数,它们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对
象中参数的位置:_1为newCallable的第一个参数,_2为第二个参数,以此类推。
原型
template <class Fun, class... Args>
bind (Fun&& fun, Args&&... args);
template <class Ret, class Fun, class... Args>
bind (Fun&& fun, Args&&... args);
2.引入
2.1现有语法无法解决
int Myplus(int a, int b)
{
return a + b;
}
class Sub
{
public:
int Mysub(int a, int b)
{
return a - b;
}
};
int main()
{
function<int(int, int)> funcPlus = Myplus;
function<int(Sub, int, int)> funcSub = &Sub::Mysub;
map<string, function<int(int, int)>> m =
{
{ "+", Myplus},
{ "-", &Sub::Mysub}
};
}
即 一个全局函数 一个类 现在我们想要把这两个函数通过包装器包装起来 我们的目的无法达到 因为两个函数传给包装器时 方式不同 包装时无法统一 怎么解决?
class Mycalculator
{
public:
int Myplus(int a, int b)
{
return a + b;
}
int Mysub(int a, int b)
{
return a - b;
}
};
int main()
{
function<int(Mycalculator,int, int)> funcPlus = &Mycalculator::Myplus;
function<int(Mycalculator, int, int)> funcSub = &Mycalculator::Mysub;
map<string, function<int(Mycalculator, int, int)>> m =
{
{ "+", &Mycalculator::Myplus},
{ "-", &Mycalculator::Mysub}
};
}
很明显 上面强制他们统一 同样的也可以把类转成全局函数 但这都不是我们想要的结果 怎么办呢???
此时 bind绑定就出来了…
2.2bind的文档阅读
返回一个基于fn的函数对象,但其参数绑定为args。
每个实参可以绑定到一个值或一个占位符:
-如果绑定到一个值,调用返回的函数对象将始终使用该值作为参数。
-如果是占位符,调用返回的函数对象会将一个参数传递给调用(其顺序号由占位符指定)。
调用返回的对象返回与fn相同的类型,除非指定了特定的返回类型为Ret(2)(注意,Ret是唯一不能通过传递给此函数的实参隐式推断的模板形参)。
返回对象的类型具有以下属性:
它的函数调用返回与fn相同的参数绑定到args…(或转发,用于占位符)。
对于(1),它可以有一个成员result_type:如果Fn是指向函数或成员函数类型的指针,它被定义为其返回类型的别名。否则,如果存在这样的成员类型,则定义为Fn::result_type。
对于(2),它有一个成员result_type,定义为Ret的别名。
它是可移动构造的,如果它的所有参数的类型都是可复制构造的,那么它也是可复制构造的。两个构造函数都不会抛出,只要没有相应的Fn和Args衰变类型的构造函数…扔。
fn
函数对象,指向函数的指针或指向成员的指针。
Fn应具有可从Fn移动构造的衰变类型。
args……
要绑定的参数列表:值或占位符。
Args中的类型…应具有可从args…中各自的参数移动构造的衰变类型
如果对于任何参数,其衰减类型是reference_wrapper,则将其绑定到其引用的值。
一个函数对象,被调用时调用fn,其参数绑定到args。
如果fn是指向成员的指针,则返回函数期望的第一个参数是类的对象*fn是成员(或对其的引用,或指向其的指针)。
namespace placeholders
{
extern /* unspecified */ _1;
extern /* unspecified */ _2;
extern /* unspecified */ _3;
// ...
}
2.3bind()绑定函数对于2.1问题的解决
int pLus(int a, int b)
{
return a + b;
}
class Sub
{
public:
int sub(int a, int b)
{
return a - b;
}
};
int Mul(int a, int b, int c)
{
return a * b * c;
}
int Div(int a, int b)
{
return a / b;
}
using namespace placeholders;
int main()
{
function<int(int, int)> funcPlus = pLus;
//function<int(Sub, int, int)> funcSub = &Sub::sub;
function<int(int, int)> funcSub = bind(&Sub::sub, Sub(), _1, _2);
function<int(int, int, int)> funcMul = bind(Mul, _1, _2, _3);
map<string, function<int(int, int)>> m =
{
{ "+", pLus},
{ "-", bind(&Sub::sub, Sub(), _1, _2)}
};
cout << "funcPlus(1, 2) == " << funcPlus(1, 2) << endl << endl;
cout << "bind(&Sub::sub, Sub(), _1, _2) == " << funcSub(1, 2) << endl << endl;
cout << "bind(Mul, _1, _2, _3) == " << funcMul(1, 2, 3) << endl << endl;
auto funcMul2 = bind(Mul, 1, 2, 3);
cout << "funcMul2() == " << funcMul2() << endl << endl;
cout << "m["" + ""](1, 2) == " << m["+"](1, 2) << endl << endl;
cout << "m["" - ""](1, 2) == " << m["-"](1, 2) << endl << endl;
return 0;
}