写在前面
最近工作中碰到了之前没有接触的std::function函数模板类, 抽闲学习一二。
std::function是一个函数包装器,包含在头文件中。该函数包装器模板能包装任何类型的可调用实体,如普通函数、函数对象、lambda表达式。
声明
基本语法:function<函数模板类型> 包装器名;
其中函数模板类型无需函数名,不可省略返回值和参数列表。如下:
#include <funcitonal>
using namespace std;
function<void ()> func;
//function<void tmp()> func; //错误,无需函数名
//function<void > func; //错误,无参数列表
//function<(int)> func; //错误,无返回类型
示例
下面示例简单展示了通过std::function 包装普通函数、函数指针、Lambda表达式等。
int square(int val)
{
return val * val;
}
typedef int (* FnSquare)(int);
class FuncTmp
{
public:
void operator()()
{
cout << "Tmp \n";
}
};
int main()
{
int a = 5;
function<int (int)> func1 = square; //包装普通函数
FnSquare fnSquare = square;
function<int (int)> func2 = fnSquare; //包装函数指针
function<void ()> func3 = FuncTmp(); //包装仿函数(函数对象)
function<void (int)> func4 = [](int a){ //包装Lambda表达式
cout << "a: " << a << endl;
};
cout << func1(a) << endl;
cout << func2(2) << endl;
func3();
func4(10);
return 0;
}
**函数包装器对象未包装任何可调用对象时,其值未空。**因此使用前可先判空
function<void ()> func;
if (func)
{
//非空,有包装可调用对象
}
else
{
//空,未包装任何可调用对象
//func(); //空值调用会抛出异常终止程序
}
当包装器中的函数声明和原型不同时,编译会报错,因此需保证模板类型和原型一致:
void test(int& val)
{
val = 100;
}
//这里模板类型和函数原型不一致,编译报错:error C2440: “初始化”: 无法从“void (__cdecl *)(int &)”转换为“std::function<void (int)>”
function<void(int)> func5 = test;
if (func5)
{
int val = 0;
func5(val);
cout << val << endl;
}
总结
若不想通过typedef声明函数指针,或想保存Lambda表达式,则可以考虑使用std::function。