function函数包装器也叫适配器,在C++中其本质是一个类模板。
由于C++的历史遗留问题,导致如果想实现一个函数功能,可以采用函数名、函数指针、仿函数、有名称的lambda表达式,所有这些都是可调用的类型。
它们存在很多问题:
比如ret=func(x)
这个函数调用,func有可能是上面的任意一种。
类型如此丰富,可能导致模板的效率极低。
#include
using namespace std;
template<class F,class T>
T useF(F f, T x)
{
static int count = 0;
cout << "count:" << ++count << endl;
cout << "count:" << &count << endl;
return f(x);
}
double f(double i)
{
return i / 2;
}
struct Functor
{
double operator()(double d)
{
return d / 3;
}
};
int main()
{
cout << useF(f, 11.11) << endl;
cout << useF(Functor(), 11.11) << endl;
cout << useF([](double d)->double {return d / 4; }, 11.11) << endl;
return 0;
}
编译器会根据传入的F类型不同,实例化出三种不同的函数,所以静态变量count就会有三种不同的地址。
很显然这并不很合适,因为不管是函数名、函数指针、仿函数还是lambda表达式,它们都是一个“函数”,所以如果它们能够统一类型,这样模板就会实例化出一份对象,从而提高效率。
包装器可以很好地解决这个问题,它统一可调用对象类型,并且指定了参数和返回值类型。
function
函数包装器的写法为:
function<函数返回值类型(函数参数类型)>包装器名称=要包装的函数。
其在头文件
中
#include
#include
using namespace std;
template<class F,class T>
T useF(F f, T x)
{
static int count = 0;
cout << "count:" << ++count << endl;
cout << "count:" << &count << endl;
return f(x);
}
double f(double i)
{
return i / 2;
}
struct Functor
{
double operator()(double d)
{
return d / 3;
}
};
class Func
{
public:
static double f1(double i)
{
return i / 4;
}
double f2(double i)
{
return i / 5;
}
};
int main()
{
function<double(double)>func1 = f;
function<double(double)>func2 = Functor();
function<double(double)>func3 = [](double d)->double {return d / 4; };
function<double(double)>func4 = Func::f1;
//非静态成员函数要传this指针,因此参数要加上Func,且要取地址
function<double(Func,double)>func5 = &Func::f2;
//调用包装器包装的函数
cout << func1(11.11) << endl;
cout << func2(11.11) << endl;
cout << func3(11.11) << endl;
cout << func4(11.11) << endl;
//传入非静态成员函数时,要额外传入一个对象
cout << func5(Func(),11.11) << endl;
//func1到func5都会被当做一种类型
cout << useF(func1, 11.11) << endl;
cout << useF(func2, 11.11) << endl;
cout << useF(func3, 11.11) << endl;
cout << useF(func4, 11.11) << endl;
//cout << useF(func5, 11.11) << endl;
return 0;
}
可以将bind函数看作是一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原来对象的参数列表。它可以用来绑定一个类对象,这样调用绑定的成员函数时就不需要传入一个类对象了。
#include
#include
using namespace std;
int Plus(int a, int b)
{
return a + b;
}
class Sub
{
public:
int sub(int a, int b)
{
return a - b;
}
};
int main()
{
function<int(int,int)>f1=bind(Plus, placeholders::_1, placeholders::_2);
cout << f1(1, 2) << endl;//3
//把plus绑定成一个值+10,相当于只传一个参数,另一个参数固定为10
function<int(int)>f2 = bind(Plus, 10, placeholders::_1);
cout << f2(4) << endl;//14
//绑定很好地解决了调用成员函数必须要先出入一个对象的问题,它直接绑定了一个对象
function<int(int, int)>f3 = bind(&Sub::sub, Sub(), placeholders::_1, placeholders::_2);
cout<<f3(1, 2) << endl;//-1
//控制传入参数的顺序,将 placeholders::_1和 placeholders::_2交换顺序
//这样传入的第一个参数就会作为sub(int a,int b)中的b,第二个参数作为a
//这主要是因为_2是和b绑定的,_1和a绑定,先传入的参数是_2,再传入_1
function<int(int, int)>f4 = bind(&Sub::sub, Sub(), placeholders::_2, placeholders::_1);
cout << f4(1, 2) << endl;//1
return 0;
}