AndyW
AndyW

Reputation: 111

C++ Retaining a Lambda Expression in an Object

Okay, so I'm writing a simple GUI framework. I stumbled across lambda expressions and thought they'd be a good way to do callbacks. But I can't figure out how to retain the expression in class (very simplified example code below).

class class1
{
public:
  class1(auto callback);
private:
  const auto mCallback  
};
class1::class1(auto callback) : mCallback(callback)
{

}
int main()
{
    auto thiscode = [] (int id) 
    {
        std::cout<<"callback from..." << id << std::endl;
    };
    class1 c1 = class1(thiscode);
}

I end up with this error,

error: non-static data member declared 'auto'

Which I suppose makes sense, it can't determine the size at run time. In fact, below C++14 it won't even allow me to pass auto callback as a paramter to the constructor. (I think that changed in a readying process for concepts?).

How do I get around this? I don't mind having to do something weird, anything that allows me to retain a reference to the passed lambda expression - I'm golden with.

Upvotes: 2

Views: 144

Answers (2)

wally
wally

Reputation: 11032

You can use std::function to store thiscode.

Something like this:

#include <functional>
#include <iostream>

class class1 {
public:
    class1(std::function<void(int)> callback) : mCallback{callback} {};
    void do_callback() { mCallback(3); };
private:
    const std::function<void(int)> mCallback;
};

int main()
{
    auto thiscode = [](int id) {
        std::cout<<"callback from..." << id << std::endl;
    };
    class1 c1 = class1(thiscode);
    c1.do_callback();
    return 0;
}

See live demo here.

Upvotes: 4

Guillaume Racicot
Guillaume Racicot

Reputation: 41840

You can hold them with templates

template<typename T>
class class1
{
public:
    class1(T callback): mCallback{std::move(callback)} {}
private:
    const T mCallback  
};

template<typename T>
auto makeClass1(T&& callback) {
    return class1<std::decay_t<T>>{std::forward<T>(callback)};
}

int main()
{
    auto thiscode = [] (int id) 
    {
        std::cout<<"callback from..." << id << std::endl;
    };
    auto c1 = makeClass1(thiscode);
}

Or alternatively, you can hold them with std::function:

class class1
{
public:
  class1(std::function<void(int)> callback);
private:
  const std::function<void(int)> mCallback  
};

int main()
{
    auto thiscode = [] (int id) 
    {
        std::cout<<"callback from..." << id << std::endl;
    };
    class1 c1 = class1(thiscode);
}

Upvotes: 3

Related Questions