29-修复问题
18.5.2 修复问题
包装器function让您能够重写上述程序,使其只使用use_f()的一个实例而不是5个。注意到程序清单18.7中的函数指针、函数对象和lambda表达式有一个相同的地方,它们都接受一个double参数并返回一个double值。可以说它们的调用特征标(call signature)相同。调用特征标是由返回类型以及用括号括起并用逗号分隔的参数类型列表定义的,因此,这六个实例的调用特征标都是double (double)。
模板function是在头文件functional中声明的,它从调用特征标的角度定义了一个对象,可用于包装调用特征标相同的函数指针、函数对象或lambda表达式。例如,下面的声明创建一个名为fdci的function对象,它接受一个char参数和一个int参数,并返回一个double值:
std::function<double(char, int)> fdci;
然后,可以将接受一个char参数和一个int参数,并返回一个double值的任何函数指针、函数对象或lambda表达式赋给它。
在程序清单18.7中,所有可调用参数的调用特征标都相同:double (double)。要修复程序清单18.7以减少实例化次数,可使用function<double(double)>创建六个包装器,用于表示6个函数、函数符和lambda。这样,在对use_f()的全部6次调用中,让F的类型都相同(function<double(double)>),因此只实例化一次。据此修改后的程序如程序清单18.8所示。
程序清单18.8 wrapped.cpp
//wrapped.cpp -- using a function wrapper as an argument
#include "somedefs.h"
#include <iostream>
#include <functional>
double dub(double x) {return 2.0*x;}
double square(double x) {return x*x;}
int main()
{
using std::cout;
using std::endl;
using std::function;
double y = 1.21;
function<double(double)> ef1 = dub;
function<double(double)> ef2 = square;
function<double(double)> ef3 = Fq(10.0);
function<double(double)> ef4 = Fp(10.0);
function<double(double)> ef5 = [](double u) {return u*u;};
function<double(double)> ef6 = [](double u) {return u+u/2.0;};
cout << "Function pointer dub:\n";
cout << " " << use_f(y, ef1) << endl;
cout << "Function pointer square:\n";
cout << " " << use_f(y, ef2) << endl;
cout << "Function object Fp:\n";
cout << " " << use_f(y, ef3) << endl;
cout << "Function object Fq:\n";
cout << " " << use_f(y, ef4) << endl;
cout << "Lambda expression 1:\n";
cout << " " << use_f(y, ef5) << endl;
cout << "Lambda expression 2:\n";
cout << " " << use_f(y,ef6) << endl;
return 0;
}
下面是该程序的示例输出:
Function pointer dub:
use_f count = 1, &count = 0x404020
2.42
Function pointer sqrt:
use_f count = 2, &count = 0x404020
1.1
Function object Fp:
use_f count = 3, &count = 0x404020
11.21
Function object Fq:
use_f count = 4, &count = 0x404020
12.1
Lambda expression 1:
use_f count = 5, &count = 0x404020
1.4641
Lambda expression 2:
use_f count = 6, &count = 0x404020
1.815
从上述输出可知,count的地址都相同,而count的值表明,use_f() 被调用了6次。这表明只有一个实例,并调用了该实例6次,这缩小了可执行代码的规模。