1. 包装器
1.1 function
std::function 是⼀个类模板,也是⼀个包装器。 std::function 的实例对象可以包装存
储其他的可以调⽤对象,包括函数指针、仿函数、 lambda 、 bind 表达式等,存储的可调⽤对
象被称为 std::function 的⽬标。若 std::function 不含⽬标,则称它为空。调⽤空**
std::function 的⽬标*导致抛出 std::bad_function_call 异常。*
格式形式

Ret是返回类型,Args是可变参数。
function的适用环境:
当我们想要在一个容器里面存储,可调用函数的类型有很多,函数指针,仿函数,和lambda表达式。它们的类型都不一样。lambda的表达式类型我们也不知道啊,只有编译器才能推导。
function就可以很好处理这种情况,它利用类型擦除,隐含类型,把它们储存在一块空间,减少空间的使用.
1.1.1对于全局函数,仿函数,lambda
cpp
using namespace std;
//function的包装器的用法
int fun(int x,int y ) {
return x + y;
}
struct funter {
int operator()(int x,int y) {
return x + y;
}
};
class op {
public:
static int cun(int x,int y) {
return x + y;
}
//非静态成员函数
int con(int x, int y) {
return x + y;
}
};
int main() {
//函数指针的类型复杂,仿函数的类型,lambda表达式类型我们不知道,一般都是编译器推导的。
//可调用对象的类型都不一样,那我们怎么才能储存在一个容器里面了。
//这个需要利用到function,它会隐含可调用函数的类型,然后存在在一块空间。function里面用到一个叫类型擦除的方法。
//function的格式,function<返回类型<参数>>;
vector<std::function<int(int , int )>> v;
std::function<int(int , int )> f1 = fun;//参数的括号不要写错了
std::function<int(int , int )> f2 = funter();//参数列表只需要类型,不要参数名。
std::function<int(int , int )> f3 = [](int x, int y) {return x + y; };
cpp
vector<std::function<int(int , int )>> v;
std::function<int(int , int )> f1 = fun;//参数的括号不要写错了
std::function<int(int , int )> f2 = funter();//参数列表只需要类型,不要参数名。
std::function<int(int , int )> f3 = [](int x, int y) {return x + y; };
cout << f1(1, 1) << endl;
cout << f2(1, 1) << endl;
cout << f3(1, 1) << endl;
v.push_back(f1);
v.push_back(f2);
v.push_back(f3);
for (auto& e : v) {
cout << e(2,3) << endl;
}
代码运行如下:

1.1.2成员函数的包装
对于成员函数指针的包装,有许多值得注意的地方。
cpp
class op {
public:
static int cun(int x,int y) {
return x + y;
}
//非静态成员函数
int con(int x, int y) {
return x + y;
}
};
cpp
//包装成员函数
//静态成员函数
op t3;
function<int(int, int)> d1 = &op::cun;//对于成员函数,获取函数指针必须前面加类域//静态前面可以加&
function<int(op*,int, int)> d2 = &op::con;//这里参数con函数里面成员函数,还有隐含的this指针。
function<int(op, int, int)> d3 = &op::con;//还可以传这个,
function<int(op&&,int, int)> d4 = &op::con;
cout << d1(1, 1)<<endl;
cout << d2(&t3,2, 1) << endl;
cout << d3(op(),4, 1) << endl;
cout << d4(op(),6, 1) << endl;
cout << d4(move(t3), 7, 3) << endl;
首先对于static静态成员函数需要加域名,&符号可以加,但是为了统一推荐加
对于成员函数,访问函数的指针,必须加&, function<int(op*,int, int)> d2 = &op::con;再看这个参数,里面为什么有op*,因为成员函数里面有this指针。参数可以是对象,对象指针,右值引用,左值引用。
为什么可以传op,op*?
因为this指针不是直接传给函数,不能显示传,底层通过对象(.*)调用,或者对象指针->*调用
cpp
///op* t1=&t3;//这个指针要初始化,因为//op*t1只是声明
op* t1 = new op();
auto ptr = &op::con;
cout<<(t1->*ptr)(1, 2)<<endl;
op t2;
cout << (t2.*ptr)(3, 4) << endl;
输出的时候:对于成员函数,我们参数要传对象,匿名对象。对象的地址。
运行代码:

1.2 算法题function的用法
1.3bind
-
对于bind我们可以把看它看作一个函数模板,一个可调用对象的包装器,一个函数适配器。它把一个可调用函数处理后,返回一个可调用函数参数。bind可改变参数个数和顺序。它的头文件是<functional>。
-
调⽤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为第⼆个参数,以此类推。_1/_2/_3....这些占 位符放到placeholders的⼀个命名空间中。
cpp
int fun(int x,int y) {
return (x - y) * 10;
}
int fun1(int x, int y,int z) {
return (x - y-z) * 10;
}
int main() {
auto d1 = bind(fun, _1, _2);
cout << d1(10, 5)<<endl;
auto d2 = bind(fun, _2, _1);//bind 本质是返回一个仿函数对象。
cout << d2(10, 5) << endl;//这里调用可调用函数,调用它的operator(),然后再调用fun函数。
//调整参数个数
auto d3 = bind(fun1, 15, _1, _2);
cout << d3(10, 5) << endl;
auto d4 = bind(fun1, _1, 15, _2);
cout << d4(10, 5)<<endl;
使用场景:
绑定this指针的参数
cpp
function<int(op, int, int)> d3 = &op::con;//还可以传这个,
// function<int(op&&,int, int)> d4 = &op::con;
//
// cout << d1(1, 1)<<endl;
// cout << d2(&t3,2, 1) << endl;
// cout << d3(op(),4, 1) << endl;
// cout << d4(op(),6, 1) << endl;
相比较
//对于类成员函数的包装,我们调用的时候,每次都需要传类对象,来调用隐含的this指针。我们可不可以把强制把参数设置。
function<int( int, int)> d5 = bind(&op::con,op(),_1,_2);//只有两个可变参数
cout << d5(16, 4)<<endl;
计算利息的场景
cpp
int sum(double x, double money, int year) {
double ret = money;
while (year) {
ret = ret + ret * x;
year--;
}
return ret-money;
}
//对于银行利息的计算
//一般利率是固定的,
auto _m_1 = bind(sum, 0.1, _1, 1);
auto _m_3 = bind(sum, 0.1, _1, 3);
auto _m_5 = bind(sum, 0.1, _1, 5);
cout << _m_1(10000) << endl;
cout << _m_3(10000) << endl;
cout << _m_5(10000)<<endl;