繁体   English   中英

如何在 C++11 中将 lambda 表达式存储为类的字段?

[英]How can I store a lambda expression as a field of a class in C++11?

我想创建一个类,客户端可以在其中存储像[]() -> void {}这样的 lambda 表达式作为类的字段,但我不知道如何这样做。 一个答案建议使用decltype ,我尝试过但没有成功。 这是ideone 源链接 下面是源码和结果:

#include <cstdio>
auto voidLambda = []()->void{};

class MyClass {
public:
     decltype(voidLambda) t;
     MyClass(decltype(voidLambda) t) { 
        this->t = t;
     }
};

int main() {
   MyClass([] {
      printf("hi");
   });
}

结果:

prog.cpp: In constructor 'MyClass::MyClass(<lambda()>)':
prog.cpp:3:79: error: no matching function for call to '<lambda()>::__lambda0()'
prog.cpp:2:20: note: candidates are: <lambda()>::<lambda>(const<lambda()>&)
prog.cpp:2:20: note:                 <lambda()>::<lambda>(<lambda()>&&)
prog.cpp:3:88: error: no match for 'operator=' in '((MyClass*)this)->MyClass::t = t'
prog.cpp: In function 'int main()':
prog.cpp:5:27: error: no matching function for call to 'MyClass::MyClass(main()::<lambda()>)'
prog.cpp:3:48: note: candidates are: MyClass::MyClass(<lambda()>)
prog.cpp:3:14: note:                 MyClass::MyClass(const MyClass&)

有谁知道如何做到这一点?

如果您希望类成员成为 lambda 表达式,请考虑使用std::function<>包装类型(来自<functional>标头),它可以保存任何可调用函数。 例如:

std::function<int()> myFunction = []() { return 0; }
myFunction(); // Returns 0;

这样,您就不需要知道 lambda 表达式的类型。 您可以只存储适当函数类型的std::function<> ,模板系统将为您处理所有类型。 更一般地,任何具有适当签名的可调用实体都可以分配给std::function<> ,即使该函子的实际类型是匿名的(在 lambdas 的情况下)或非常复杂。

std::function模板内部的类型应该是与您要存储的函数相对应的函数类型。 因此,例如,要存储一个接受两个int并返回 void 的std::function<void (int, int)> ,您需要创建一个std::function<void (int, int)> 对于不带参数并返回int std::function<int()> ,您可以使用std::function<int()> 在您的情况下,由于您想要一个不带参数并返回void的函数,因此您需要这样的东西:

class MyClass { 
public:
    std::function<void()> function;
    MyClass(std::function<void()> f) : function(f) {
        // Handled in initializer list
    }
};

int main() {
    MyClass([] {
        printf("hi")
    }) mc; // Should be just fine.
}

希望这可以帮助!

我能想到的在类中存储 lambda 的唯一方法是使用带有辅助make_函数的模板:

#include <cstdio>
#include <utility>

template<class Lambda>
class MyClass {
    Lambda _t;
public:
    MyClass(Lambda &&t) : _t(std::forward<Lambda>(t)) {
        _t();
    }
};

template<class Lambda>
MyClass<Lambda> make_myclass(Lambda &&t) {
    return { std::forward<Lambda>(t) };
}

int main() {
    make_myclass([] {
        printf("hi");
    });
}

void ()情况下可以使用简单的函数指针(声明语法是void (*pointer_name) (); )。 带有空捕获块的 Lambda 可隐式转换为具有相同签名的函数指针。 并且std::function有运行时和大小( std::function至少大三倍)开销。

struct S
{
  void (*f_p)() {}; // `{}` means `= nullptr`;
};

int main()
{
    S s { [] { std::cout << "Lambda called\n"; }};

    s.f_p();

    S s2;
    if (s2.f_p) // check for null
        s.f_p();

    s2.f_p = [] { std::cout << "Lambda2 called\n"; };
    s2.f_p();

    s2.f_p = std::terminate; // you can use regular functions too

    s2.f_p();
}

输出

Lambda called
Lambda2 called
terminate called without an active exception

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM