功能:
包装器function能够提供统一的方式处理各种类似于函数的形式。
解决的问题:
解决模板低效性问题,例如:
template <typename T, typename F>
T use_f(T v, F f)
{
static int count = 0;
count++;
std::cout << " use_f count = " << count
<< ", &count = " << &count << std::endl;
return f(v);
}
模板use_f使用参数f表示调用类型:return f(v);
如果使用不同的参数调用use_f,并且不论是函数对象、函数指针、Lamda表达式,所有可调用参数的调用特征标都相同:double(double),即输入double类型,返回double类型,在这种情况下,发现模板并不会因为F类型相同只实例化模板一次,根据&count可以看出,输出不同的地址,这表明实例化了多次;
例如:
double dub(double x)
{
return 2.0 * x;
}
class Fp
{
private:
double z_;
public:
Fp(double z = 1.0) : z_(z) {}
double operator()(double p}
{
return z_ * p;
}
};
int main() {
double y = 1.21;
cout << use_f(y, dub) << endl;
cout << use_f(y, Fp(0.5) << endl;
cout << use_f(y, [](double u) {return u * u;}) << endl;
return 0;
}
三者&count值不同,表明模板实例化了三次。
修复问题
模板function是在头文件functional中声明的,它从调用特征标的角度定义了一个对象,可用于包装调用特征标相同的函数指针、函数对象、lambda表达式。
方法一:
例如:创建一个名为foo的function对象,它接受一个char参数和一个int参数,并返回一个double值
std::function<double(char, int)> foo;
那么对于上述问题,可以通过创建多个function对象或者临时对象来解决:
cout << use_f(y, function<double(double)> (dub) << endl;
cout << use_f(y, function<double(double)> (Fp(0.5) << endl;
cout << use_f(y, function<double(double)> ([](double u) {return u * u;}) << endl;
输出结果表明,&count值相同,count值依次增加,因此模板use_f只实例化了一次;
方法二:
除了让use_f的第二个实参与形参f匹配之外,还可以让形参f的类型与原始实参匹配:
template <typename T, typename F>
T use_f(T v, std::function<T(T)> f)
{
static int count = 0;
count++;
std::cout << " use_f count = " << count
<< ", &count = " << &count << std::endl;
return f(v);
}
// 函数调用如下
...
cout << use_f<double>(y, dub) << endl;
cout << use_f<double>(y, Fp(0.5)) << endl;
cout << use_f<double>(y, [] (double u) {return u * u;}) << endl;
参数dub、Fp(0.5)等本身类型并不是function<double(double)>,因此在use_f后面使用<double>来指出所需的具体化,这样,T被置为double,而std::function<T(T)>变成了std::function<double(dobule)>。