Immediate callback
Consider the following example:
template <typename lambda> void call_me_back(const lambda & callback)
{
// Very complicated calculation to find the meaning of everything
callback(42);
}
int main()
{
call_me_back([](const int & value)
{
std :: cout << value << std :: endl;
});
}
Here I provide call_me_back
with a lambda that accepts an int
. call_me_back
calls callback
after some long calculation, and callback
prints it out. Easy as cake.
Now, say that depending on the execution, call_me_back
needs to call callback
either with an int
or with some other type. We can edit the previous example to
template <typename lambda> void call_me_back(const lambda & callback)
{
// Very complicated calculation to find the meaning of everything
if(rand() % 2)
callback(42);
else
callback("Kill all the humans.");
}
int main()
{
call_me_back([](const auto & value)
{
std :: cout << value << std :: endl;
});
}
So far so good. Now callback
can do all sorts of tricks and handle value
depending on its type.
Delayed callback
Now, back to the first example. Say that call_me_back
is not ready to immediately call callback
with an int
. What it can do, however, is to store the callback
somewhere, and then call it later.
For example:
std :: function <void(const int &)> the_callback;
template <typename lambda> void call_me_back(const lambda & callback)
{
the_callback = callback;
}
void ready_to_answer()
{
the_callback(42);
}
int main()
{
call_me_back([](const auto & value)
{
std :: cout << value << std :: endl;
});
}
Now, instead of immediately calling callback
, call_me_back
stores callback
in an std :: function <void(const int &)>
object (I know, it's in the global scope, bear with me). Many things can then happen and at some point someone can call ready_to_answer
, which retrieves the previously stored callback and calls it. For example, ready_to_answer
can be called by another thread, but there is a whole lot of reasons why one would need a paradigm like this, where the callback can be stored and called later.
The problem
What if I wanted to implement the second example, but with a delayed callback?. I don't seem to be able to get my head around this.
I can imagine that std :: function
is implemented with a virtual call operator that accepts some specific type. The std :: function
then wraps a pointer / reference to a template wrapper class that stores the actual lambda and implements the call operator by forwarding its argument to the lambda it's storing. Nice and easy. But I can't have template virtual methods!
I have tried coming up with all sorts of solutions, but I couldn't find anything that could reasonably work. Is this really impossible to do? Is it impossible to have some externally provided lambda that accepts a const auto &
argument stored somewhere, and then call it later?