包装器 function

以统一的方式处理多种类似于函数的形式。在头文件#include<functional>中

包装器

解决问题

        对于ef,只要是可调用对象就行,可以是函数、函数指针、函数对象、lambda表达式。由于可调用类型的多种多样,会导致模板的效率降低(会实例化多次),同时对于每一种不同的调用类型在调用时必须编写和其匹配的调用方法,程序不灵活。下面请看示例:

问题:

 

template<class T,class F>
T use_f(T v, F f)
{
	static int count = 0;
	count++;
	cout << "count = " << count << endl;
	cout << "&count = " << &count << endl;
	return f(v);//使用参数f表示调用类型
}

class TestA
{
private:
	int a_;
public:
	TestA(int a = 1) :a_(a) {}
	int operator()(int p) { return a_ * p; }
};

class TestB
{
private:
	int b_;
public:
	TestB(int b = 1) :b_(b) {}
	int operator()(int q) { return b_ * q; }
};

int dub(int x) { return 2 * x; }
int square(int x) { return x * x; }

int main()
{
	int x = 10;
	cout << "Function pointer dub: " << use_f(x, dub) << endl;
	cout << "Function pointer square: " << use_f(x, square) << endl;
	cout << "Function object TeatA: " << use_f(x, TestA(5)) << endl;
	cout << "Function object TeatB: " << use_f(x, TestB(5)) << endl;
	cout << "Lambda expression 1: " << use_f(x, [](int n) {return n * n; }) << endl;
	cout << "Lambda expression 2: " << use_f(x, [](int n) {return 2 * n; }) << endl;
	return 0;
}

        在每次调用时,模板参数T 都被设置为int 类型,F 表示的调用类型都是接受一个int 类型的参数返回int 类型的值,但即使F 的类型相同,模板还是实例化5次(count有5个不同的地址),只有对于两个函数指针调用类型实例化了一次,所以程序即使使用了模板还是效率很低。

原因:

编译器在编译的时候对于函数指针都是:int(*) (int),对于不同的函数对象就需要实例化两次,最后两个调用会将F 的类型设置为编译器为lambda表达式使用的类型。

解决方法:

        为了使得模板只用实例化一次,提高程序的效率,使用包装器funciton。

        虽然上述有多个可调用类型,但是都有共同的调用特征,都是接受一个int 参数并返回一个int 值。(书上解释的是调用特征标(call signature)相同,调用特征标是由返回类型以及用括号括起并用逗号分隔的参数类型列表定义的,因此,这六个实例的调用特征标都是int (int))。

        模板function 在头文件functional 中声明,它从调用特征的角度定义了一个对象,可用于包装调用特征标相同的函数指针、函数对象或lambda 表达式。

常用通项语法: std::function<return-type(args-list)> renamed_f = init_function_name

int main()
{
	int x = 10;
	function<int(int)> f1 = dub;
	function<int(int)> f2 = square;
	function<int(int)> f3 = TestA(5);
	function<int(int)> f4 = TestB(5);
	function<int(int)> f5 = [](int n) {return n * n; };
	function<int(int)> f6 = [](int n) {return 2 * n; };
	cout << "Function pointer dub: " << use_f(x, f1) << endl;
	cout << "Function pointer square: " << use_f(x, f2) << endl;
	cout << "Function object TeatA: " << use_f(x, f3) << endl;
	cout << "Function object TeatB: " << use_f(x, f4) << endl;
	cout << "Lambda expression 1: " << use_f(x, f5) << endl;
	cout << "Lambda expression 2: " << use_f(x, f6) << endl;
	return 0;
}

 

count 的值都相同,说明只有一个实例,被调用了六次,这缩小了可执行代码的规模。

同时,也可以利用重命名技术简化程序,减少代码的冗余;或者将模板中第二个参数声明为function包装器对象:

int main()
{
	int x = 10;
	typedef function<int(int)> ff;
	cout << "Function pointer dub: " << use_f(x, ff(dub)) << endl;
	cout << "Function pointer square: " << use_f(x, ff(square)) << endl;
	cout << "Function object TeatA: " << use_f(x, ff(TestA(5))) << endl;
	cout << "Function object TeatB: " << use_f(x, ff(TestB(5))) << endl;
	cout << "Lambda expression 1: " << use_f(x, ff([](int n) {return n * n; })) << endl;
	cout << "Lambda expression 2: " << use_f(x, ff([](int n) {return 2 * n; })) << endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值