作者:viper-zhu_890_552 | 来源:互联网 | 2022-12-07 18:26
我想在C++中编写一个将lambda函数保存为成员变量的类.尽可能高效地做它会很棒.例如,我读了这个线程为什么编译器可以比普通函数更好地优化lambdas?因此我想避免使用函数指针.
到目前为止,我最好的解决方案如下:
template
class LambdaClass {
private:
F lambdaFunc;
public:
LambdaClass(F &_lambdaFunc): lambdaFunc(_lambdaFunc) {}
};
我会用这个类如下:
auto lambdaFunc = [](int _a) -> int { return _a; };
LambdaClass lambdaClassObject(lambdaFunc);
在我看来,使用它看起来并不好玩.所以我首先感兴趣的是,如果编译器可以内联已保存成员lambda函数的调用,那么这个代码是否有效,以及如何编写这个代码更漂亮?
编辑:我正在使用C++ 11.
1> aschepler..:
在你的例子中
LambdaClass lambdaClassObject(lambdaFunc);
第二个模板参数列表是不正确的语法.这需要是公正的
LambdaClass lambdaClassObject(lambdaFunc);
因此,我感兴趣的是,如果编译器可以内联已保存成员lambda函数的调用,则此代码是高效的
是的,这个类可以以允许优化的方式使用,就像直接使用lambda一样.模板参数是lambda表达式的确切类型,模板替换在编译时发生,通常给出的结果就像在不使用模板的情况下编写代码一样.
如何编写这段代码更美观?
@ lubgr的回答已经提到了C++ 17"课程模板演绎"和"演绎指南"功能.在C++ 17之前,避免需要指定类模板参数的常用技巧是帮助程序"make function":
template
auto makeLambdaClass(F&& func) ->
LambdaClass::type>
{ return { std::forward(func); } }
现在你可以做到
auto lambdaFunc = [](int _a) -> int { return _a; };
auto lambdaClassObject = makeLambdaClass(lambdaFunc);
但要更进一步,做到
auto lambdaClassObject = makeLambdaClass( [](int _a) -> int { return _a; } );
也工作,你还需要确保该类有一个接受rvalue的构造函数,而不仅仅是一个非const左值:
template
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 gen{UniqueIntGenerator{}};