I have the following problem: I define a class task that lives within another class object. I want to save a closure inside that task class to invoke it later. Now how excactly am I supposed to initialize the task object within the container class? I can't use this at "top level" (e.g. when I use it in direct member initialization. On the other hand, when I decltype() an empty lambda it gives me the wrong type it seems as it doesn't close over this. Check out the following code:
#include <cstdio>
template <typename Callable>
struct task
{
task(Callable fn)
: fn_{fn}
{ }
auto do_stuff() {
fn_();
}
Callable fn_;
};
struct container
{
container()
: task_([this]() -> void { this->print(); })
{ }
auto print() -> void {
printf("Hello World!\n");
}
auto execute() {
task_.do_stuff();
}
task<decltype([](){})> task_;
};
int main()
{
container a;
a.execute();
}
This yields specifically:
<source>:20:12: error: no matching function for call to 'task<container::<lambda()> >::task(container::container()::<lambda()>)'
20 | : task_([this]() -> void { this->print(); })
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
How can I create a closure over this in direct member initialization or in the member initializer list?
If you want to be able to assign different functionalities to this
task_, you need type erasure:std::function<void()> task_;. Also, you need to haveprint()before ctor in your code.If you only need one functionality, then
task_is a member function basically.If neither of these suits you, you can still introduce a layer of indirection in the hierarchy,
containerBase: