Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

People also ask

What is lambda expression in C++11?

In C++11 and later, a lambda expression—often called a lambda—is a convenient way of defining an anonymous function object (a closure) right at the location where it's invoked or passed as an argument to a function.

How are lambdas stored?

The Lambda service stores your function code in an internal S3 bucket that's private to your account. Each AWS account is allocated 75 GB of storage in each Region. Code storage includes the total storage used by both Lambda functions and layers.

Does C support lambda function?

the C standard does not define lambdas at all but the implementations can add extensions. Gcc also added an extension in order for the programming languages that support lambdas with static scope to be able to convert them easily toward C and compile closures directly.

How do you call a lambda function in CPP?

A lambda is also just a function object, so you need to have a () to call it, there is no way around it (except of course some function that invokes the lambda like std::invoke ). If you want you can drop the () after the capture list, because your lambda doesn't take any parameters.


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!


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

In case of [] (empty capture) simple function pointer can be used. Declaration syntax is ReturnType (*pointer_name) (Arg1T, Arg2T); for pointer, ReturnType (&ref_name) (/*void*/); for reference (can't be null). Lambda with empty capture block is implicitly convertible to function pointer with same signature. And std::function have runtime and size (it 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