C++11 - function包装器
前言:
Vue框架:
从项目学Vue
OJ算法系列:
神机百炼 - 算法详解
Linux操作系统:
风后奇门 - linux
function包装器:
调用对象:
- 调用对象分类:
int ret = func(x);
//func可能是什么呢?
- 函数名
- 函数指针
- 仿函数对象
- lambda表达式对象
模板效率:
- 太多的调用对象,导致模板使用效率低下:
template<class F, class T>
T useF(F f, T t){
static int count = 0; //一定为static
cout<<"count : "<<count++<<endl;
cout<<"&count : "<<&count<<endl;
return f(x);
}
//f的三种类型:
double func1(double x){
return i/2;
}
struct Functor{
double operator()(double x){
return x/3;
}
};
auto func2 = [](double x){
return x/4;
};
int main(){
useF(func1, 10);
useF(Functor(), 10);
useF(func2, 10);
return 0;
}
- 运行结果:三个不同的count地址
- 原因分析:
- class F对应三种不同的具体类型
- 实例化出三种useF()函数
- 每种useF()函数含有自己创建的static变量
包装器:
作用:
- 将不同的可调用对象包装为同一类型
模板识别时也是视为同一类别 - 相当于调用对象的类型增加,
尤其是原本不好使用的auto,
现在也可以根据参数和返回值将类型记为function<()>;
用法:
- 头文件:
#include <functional>
- 声明:
//对函数/函数指针:
function<double(double)> f1 = func1;
//对仿函数类:
function<double(double)> f2 = Functor();
//对lambda表达式:
function<double(double)> f3 = func2;
包装类内函数:
包装类内静态函数:
- 几乎和包装非类内函数一样
class Calculator{
public:
int sum(int x, int y){
return x+y;
}
};
int main(){
function<int(int, int)> f4 = &Calculator::sum; //可不加&
return 0;
}
包装类内非静态函数:
- 和包装普通函数有两点区别:
- 加 & 符号
- 包装类内声明静态函数所属类
- 调用时需要传入一个实例对象
class Calculator{
public:
static int sub(int x, int y){
return x+y;
}
};
int main(){
function<int(Calculator, int, int)> f4 = &Calculator::sub;
f4(Calculator(), 1, 2);
return 0;
}
证明:
- 证明经过包装器后,所有函数都属于同一类:
#include <iostream>
#include <cstring>
#include <functional>
using namespace std;
template<class F, class T>
T useF(F f, T t){
static int count = 0; //一定为static
cout<<"count : "<<count++<<endl;
cout<<"&count : "<<&count<<endl;
return f(t);
}
double func1(double x){
return x/2;
}
struct Functor{
double operator()(double x){
return x/3;
}
};
auto func2 = [](double x){
return x/4;
};
class Test{
public:
static double sfunc(double x){
return x/5;
}
double dfunc(double x){
return x/6;
}
};
int main(){
function<double(double)> f1 = func1;
function<double(double)> f2 = Functor();
function<double(double)> f3 = func2;
useF(f1, 10);
useF(f2, 10);
useF(f3, 10);
function<double(double)> f4 = Test::sfunc;
function<double(Test, double)> f5 = &Test::dfunc;
useF(f4, 10);
cout<<"f5:"<<f5(Test(), 10);
/*
useF(f5, 10);
f5和f1~f4传参不同,所以 暂时 不能放入useF()函数中
学完绑定后即可
*/
return 0;
}
- 运行结果:
bind绑定:
作用:
调整传参顺序:
- placeholders::_n:表示当前位置值传递给函数第n个参数
void func(int x, int y){
cout<<"x:"<<x <<" "<<"y:"<<y<<endl;
}
function<int(int ,int)> f1 = bind(func, placeholders::_1, placeholders::_2);
f1(1, 2);
function<int(int ,int)> f2 = bind(func, placeholders::_2, placeholders::_1);
f2(1, 2);
- 运行结果:
1 2
2 1
调整参数个数:
- 为类内非静态函数,绑定类 + 提供对象:
class Test{
public:
static double sfunc(double x){
return x/5;
}
double dfunc(double x){
return x/6;
}
};
function<double(Test, double)> f5 = &Test::dfunc;
f5(Test(), 10);
function<double(Test, double)> f6 = bind(&Test::dfunc, Test());
f6(10);
- 将类内非静态函数 + 类对象,一步为function()绑定