我想用 C++ 编写一个将 lambda 函数保存为成员变量的类。尽可能高效地做到这一点会很棒。例如,我阅读了这个线程 Why can lambdas be better optimized by the compiler than plain functions?因此我想避免使用函数指针。
到目前为止,我最好的解决方案如下:
template<typename F>
class LambdaClass {
private:
F lambdaFunc;
public:
LambdaClass(F &_lambdaFunc): lambdaFunc(_lambdaFunc) {}
};
我会按如下方式使用这个类:
auto lambdaFunc = [](int _a) -> int { return _a; };
LambdaClass<decltype(lambdaFunc)> lambdaClassObject<decltype(lambdaFunc)>(lambdaFunc);
在我看来,使用它看起来并不有趣。所以我首先感兴趣的是这段代码是否有效,因为编译器可以内联保存的成员 lambda 函数的调用,其次如何编写更漂亮的代码?
编辑:我正在使用 C++ 11。
最佳答案
在你的例子中
LambdaClass<decltype(lambdaFunc)> lambdaClassObject<decltype(lambdaFunc)>(lambdaFunc);
第二个模板参数列表语法不正确。这需要只是
LambdaClass<decltype(lambdaFunc)> lambdaClassObject(lambdaFunc);
So I am interested in first if this code is efficient in the sense that the compiler could inline the calls of the saved member lambda function
是的,这个类可以以允许优化的方式使用,就像直接使用 lambda 一样。模板参数是 lambda 表达式的确切类型,模板替换发生在编译时,通常给出的结果就像您在不使用模板的情况下编写代码所获得的结果。
How one could write this code more beautiful?
@lubgr 的回答已经提到了 C++17 的“类模板推导”和“推导指南”功能。在 C++17 之前,避免指定类模板参数的常用技巧是辅助“make 函数”:
template <typename F>
auto makeLambdaClass(F&& func) ->
LambdaClass<typename std::decay<F>::type>
{ return { std::forward<F>(func); } }
现在你可以做
auto lambdaFunc = [](int _a) -> int { return _a; };
auto lambdaClassObject = makeLambdaClass(lambdaFunc);
但更进一步,使
auto lambdaClassObject = makeLambdaClass( [](int _a) -> int { return _a; } );
同样有效,您还需要确保该类具有接受右值的构造函数,而不仅仅是非常量左值:
template<typename F>
class LambdaClass {
private:
F lambdaFunc;
public:
LambdaClass(const F &lambdaFunc_): lambdaFunc(lambdaFunc_) {}
LambdaClass(F &&lambdaFunc_) : lambdaFunc(std::move(lambdaFunc_)) {}
};
顺便说一句,这个类将与非 lambda 的闭包类型的可调用类一起工作,因为 lambda 只是用 operator()
定义类的更方便的方法>:
class UniqueUIntGenerator
{
public:
unsigned int operator()() const noexcept
{ return num++; }
private:
static unsigned int num;
};
unsigned int UniqueIntGenerator::num = 0;
LambdaClass<UniqueIntGenerator> gen{UniqueIntGenerator{}};
关于C++ 将 lambda 函数保存为没有函数指针的成员变量以进行优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51837684/