(C++模板编程):std::function的实现

本文深入探讨了C++11中的std::function特性,展示了如何利用它包装不同类型的可调用对象。通过一个类模板CallFuncObj的实现,模拟了std::function的功能,包括接收函数指针、类对象和lambda表达式等,并通过实例演示了其用法。此外,还介绍了如何实现参数的完美转发,以确保原始参数的左值或右值属性得以保留。
摘要由CSDN通过智能技术生成

std::function的实现

【基本概念】

  • std::function:可调用对象包装器,是C++11新标准引入的类模板。
  • 需要添加头文件:#include <functional>
  • 函数名(函数指针)、具有operator()成员函数的类对象、lambda表达式等等,都属于可调用对象。

【引例】

void myfunc(int tmpvalue) //普通函数
{
	std::cout << "myfunc执行了:tmpvalue = " << tmpvalue << std::endl;
}

void callObjFunc(std::function<void(int)> cobj)
{
	cobj(120);
}
  • 调用
callObjFunc(myfunc);

callObjFunc([](int tmpvalue) {
	std::cout << "lambda表达式执行了,tmpvalue = " << tmpvalue << endl;
});
  • 输出

  • 通过范例,感受到了std::function的强大能力——接收各种可调用对象并进行实际的调用

实现类似std::function的功能

  • CallFuncObj的类模板,实现std::function的功能

【实现】

//引入一个CFObjHandler类模板,作为可调用对象处理器。
//可调用对象处理器
template <typename T,typename ...Args>
class CFObjHandler
{
public:
	virtual T invoke(Args... args) const {}; //虚函数,后续要创建子类
};

template <typename U,typename T, typename ...Args>
class CFObjHandlerChild :public CFObjHandler<T, Args...>
{
public:
	//构造函数
	CFObjHandlerChild(U&& tmpfuncobj) :functor(std::forward<U>(tmpfuncobj))  //U&&:使用右值
	{
	}
	virtual T invoke(Args... args) const //调用可调用对象
	{
		return functor(std::forward<Args>(args)...);
	};
private:
	U functor; //U是一个可调用对象类型,functor用于保存可调用对象。
};

//泛化版本(只进行了声明,是因为有特化版本必须得有泛化版本)
template <typename T>
class CallFuncObj;

//特化版本
template <typename T,typename... Args> 
class CallFuncObj<T(Args...)>  
//泛化版本中只有一个模板参数,所以这里只有一个模板参数T(Args...) 返回值和参数
//技巧:先看 class CallFuncObj<T(Args...)>  中的参数,再反推template <typename T,typename... Args> 
{
public:
	//构造函数模板
	template <typename U>
	CallFuncObj(U&& acobj) //可以接收各种可调用对象(函数对象,lambda表达式等)
	{
	    handler = new CFObjHandlerChild<U, T, Args...>(std::forward<U>(acobj));
    }
    //析构函数
    ~CallFuncObj()
    {
	    delete handler;
    }

public:
	//重载(),实现该类对象的可调用
	T operator()(Args... args) const
	{
		return handler->invoke(std::forward<Args>(args)...); //使用了std::forward实现参数的完美转发,保持原始实参的佐治或者右值性。
	}

private:
	CFObjHandler<T, Args...>* handler; //可调用对象处理器
};

void callObjFunc2(CallFuncObj<void(int)> cobj)
{		
	cobj(120); //会调用CallFuncObj类模板的operator()成员函数
}
  • T是可调用对象的返回值类型, Args...是可调用对象的参数类型,U代表是可调用对象的的整体类型。

【调用1】

callObjFunc2(myfunc);

callObjFunc2([](int tmpvalue) {
	std::cout << "lambda表达式执行了,tmpvalue = " << tmpvalue << endl;
	});
  • 输出

【调用2】

CallFuncObj<void(int)> f1 = myfunc;
f1(1200);
CallFuncObj<void(int)> f2 = [](int tmpvalue) {
	std::cout << "lambda表达式执行了,tmpvalue = " << tmpvalue << endl;
};
f2(1200);

auto ftest = [](int tmpvalue) {
	std::cout << "lambda表达式执行了,tmpvalue = " << tmpvalue << endl;
};
CallFuncObj<void(int)> f3 = ftest;
f3(1200);
  • 输出

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值