Vin*_*ent 6 c++ setter lambda c++11
考虑以下愚蠢的例子:
class MyClass
{
public:
template <class Function>
inline double f(double x, Function&& function)
{
return function(x);
}
};
Run Code Online (Sandbox Code Playgroud)
有了这个类,我可以MyClass::f(x, function)使用lambda函数调用它来执行它x,我希望没有开销.我的问题是:function作为一个可设置成员的等价物是什么MyClass?
class MyClass
{
public:
inline double f(double x)
{
return _function(x);
}
// What are the setter and the type of the protected member _function ?
};
Run Code Online (Sandbox Code Playgroud)
lee*_*mes 10
Lambda函数(以及一些其他类型的"可调用"函数)可以使用标头中的std::function模板类进行包装和存储<functional>.其模板参数是具有语法的函数签名
ReturnType(ArgumentType1, ArgumentType2, ...)
Run Code Online (Sandbox Code Playgroud)
所以在你的情况下,整个函数包装器类型变为
std::function<double(double)>
Run Code Online (Sandbox Code Playgroud)
因此,你的代码就变成了
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;
};
Run Code Online (Sandbox Code Playgroud)
std::function比函数指针的包装器"更多".您可能知道,lambda函数可以捕获变量上下文的一部分,需要将其存储在某处.std::function这样做是为了透明.
请注意,std::function不支持仿函数的重载签名/模板化调用操作符.当分配与像一个电话运营商签名函子T operator()(T value)的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;
};
Run Code Online (Sandbox Code Playgroud)
要创建这样的对象,您需要指定模板参数,如下所示:
auto myLambda = [](double x){ return x * 0.25; };
MyClass<decltype(myLambda)> myObject { myLambda };
Run Code Online (Sandbox Code Playgroud)
为了避免这种丑陋的句法开销,添加一个利用模板类型推导的"制造商"功能:
template<typename Function>
auto makeMyClass(Function && f) -> MyClass<Function> {
return MyClass<Function>(f);
}
Run Code Online (Sandbox Code Playgroud)
然后,代码变得更具可读性,auto再次使用:
auto myLambda = [](double x){ return x * 0.25; };
auto myObject = makeMyClass(myLambda);
Run Code Online (Sandbox Code Playgroud)