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

后端 未结 3 1602
余生分开走
余生分开走 2020-12-04 17:52

I\'d like to create a class where the client can store a lambda expression like []() -> void {} as a field of the class, but I can\'t figure out how to do so

相关标签:
3条回答
  • 2020-12-04 17:57

    In case of void () simple function pointer can be used (declaration syntax is void (*pointer_name) ();). Lambda with empty capture block is implicitly convertible to function pointer with same signature. And std::function have runtime and size (std::function is at least three times larger) overhead.

    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();
    }
    

    Output

    Lambda called
    Lambda2 called
    terminate called without an active exception
    
    0 讨论(0)
  • 2020-12-04 18:20

    If you want a class member to be a lambda expression, consider using the std::function<> wrapper type (from the <functional> header), which can hold any callable function. For example:

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

    This way, you don't need to know the type of the lambda expression. You can just store a std::function<> of the appropriate function type, and the template system will handle all the types for you. More generally, any callable entity of the appropriate signature can be assigned to a std::function<>, even if the the actual type of that functor is anonymous (in the case of lambdas) or really complicated.

    The type inside of the std::function template should be the function type corresponding to the function you'd like to store. So, for example, to store a function that takes in two ints and returns void, you'd make a std::function<void (int, int)>. For a function that takes no parameters and returns an int, you'd use std::function<int()>. In your case, since you want a function that takes no parameters and returns void, you'd want something like this:

    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.
    }
    

    Hope this helps!

    0 讨论(0)
  • 2020-12-04 18:21

    The only way I can think of to store a lambda in a class is to use a template with a helper make_ function:

    #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");
        });
    }
    
    0 讨论(0)
提交回复
热议问题