c++中的包装器 function

文章讨论了C++中不同类型的可调用对象导致模板效率低下的问题,并提出使用`std::function`包装器来解决,通过统一接口避免了模板多次实例化。
摘要由CSDN通过智能技术生成


前言

C++提供了多个包装器(wrapper,也叫适配器adapter)。这些对象用于给其他编程接口提供更一致或更合适的接口。

bind1stbind2ed就是两个适配器,它们让接受两个参数的函数能够与这样的STL算法匹配,即它要求将接受一个参数的函数作为参数。

C++提供了其他的包装器,包括:

  • 模板bind可替代bind1stbind2nd,但更灵活;
  • 模板mem_fn让我们能够将成员函数作为常规函数进行传递;
  • 模板referance_wrapper让我们能够创建行为像引用但可被复制的对象;
  • 包装器function让我们能够以统一的方式处理多种类似于函数的形式

包装器 function及模板的低效性

首先,我们来看看下面这句代码:

ret = func(x);

上面func可能是什么呢?那么func可能是函数名?函数指针?函数对象(仿函数对象)?也有可能是lambda表达式对象?所以这些都是可调用的类型!如此丰富的类型,可能会导致模板的效率低下!

例如我们用下面的代码进行验证:

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;
	// lamber表达式
	cout << useF([](double d)->double { return d / 4; }, 11.11) << endl;
	return 0;
}

运行得到以下结果:

在这里插入图片描述

函数模板useF() 有一个静态成员 count,可根据它的地址确定模板实例化了多少次。有3个不同的地址代表模板有3个不同的实例化。

修复问题

所以我们可以用包装器 function 来解决这个问题:

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()
{
	// 函数名
	std::function<double(double)> func1 = f;
	cout << useF(func1, 11.11) << endl;
	// 函数对象
	std::function<double(double)> func2 = Functor();
	cout << useF(func2, 11.11) << endl;
	// lamber表达式
	std::function<double(double)> func3 = [](double d)->double { return d /4; };
	cout << useF(func3, 11.11) << endl;
	return 0;
}

这个时候模板就实例化了1次,所以它们的地址相同:

在这里插入图片描述

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值