Reputation: 4759
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?
Upvotes: 1
Views: 201
Reputation: 10880
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 have print()
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
:
struct containerBase
{
void print() {
printf("Hello World!\n");
}
auto g() { return [this]() -> void { this->print(); }; }
};
struct container : containerBase
{
container()
: task_(g())
{ }
public:
auto execute() {
task_.do_stuff();
}
task<decltype(std::declval<containerBase>().g())> task_;
};
Upvotes: 2