Lambda 函数(以及一些其他类型的“可调用”函数)可以使用标头std::function
中的模板类进行包装和存储<functional>
。它的模板参数是一个函数签名,语法如下
ReturnType(ArgumentType1, ArgumentType2, ...)
所以在你的情况下,整个函数包装类型变成
std::function<double(double)>
因此,您的代码变为
class MyClass
{
public:
inline double f(double x)
{
return _function(x);
}
void setFunction(std::function<double(double)> && f)
{
_function = f;
}
private:
std::function<double(double)> _function;
};
std::function
比函数指针的包装“更多”。您可能知道,lambda 函数可以捕获需要存储在某处的变量上下文的一部分。std::function
透明地为你做这件事。
请注意,std::function
不支持函子的重载签名/模板化调用运算符。T operator()(T value)
当使用像a这样的调用操作符签名分配函子时,std::function<double(double)>
只能使用此签名调用它。所以没有std::function<T(T)>
(除非T
已经知道,比如你的类的模板参数)。
在某些情况下可能更有效的替代方法(您需要对其进行基准测试/分析)是使您的整个类成为模板类,其中函数类型参数是模板参数。然后您可以将函数存储为成员:
template<typename Function>
class MyClass
{
public:
MyClass(Function && f) :
_function(f)
{}
inline double f(double x)
{
return _function(x);
}
private:
Function _function;
};
为了创建这样的对象,您需要指定模板参数,如下所示:
auto myLambda = [](double x){ return x * 0.25; };
MyClass<decltype(myLambda)> myObject { myLambda };
为了避免这种难看的语法开销,添加一个利用模板类型推导的“maker”函数:
template<typename Function>
auto makeMyClass(Function && f) -> MyClass<Function> {
return MyClass<Function>(f);
}
然后,代码变得更具可读性,auto
再次使用:
auto myLambda = [](double x){ return x * 0.25; };
auto myObject = makeMyClass(myLambda);