I have a few questions about the implementation of the function then()
in Herb Sutter's talk. This function is used to chain asynchronous operations, the parameter f
is a future from one operation and the parameter w
is the 'work' for this operation (lambda).
template <typename Fut, typename Work>
auto then(Fut f, Work w) -> future<decltype(w(f.get()))>
{
return async([=]{ w(f.get()); });
}
An example of application would be:
std::future<int> f = std::async([]{
std::this_thread::sleep_for(std::chrono::microseconds(200));
return 10;
});
auto f2 = then(std::move(f), [](int i){
return 2 * i;
});
The main thread spawns the tasks but does not wait for any of them to finish.
Firstly, future<T>
does not have a copy constructor. This means, that the suggested implementation can be only used with shared_future<T>
unless we change the call to async()
to move the future into the lambda. This SO question suggested a way of doing it but it seems too complicated. I re-implemented the function and I am wondering whether my code is correct or whether I missed something...
Secondly, the future that is passed to the then()
function might be void
so we actually need 2 implementations of then()
, right? One for futures returning T
and one for futures returning void
.
Lastly, should the lambda inside the body of then()
not have a return statement so that we can actually return the value back? Without the return statement, then returns future<void>
, right?
I tried to address the above points and this is what I came up with. Is it correct?
template <typename T, typename Work>
auto then(future<T> f, Work w) -> future<decltype(w(f.get()))>
{
return async([](future<T> f, Work w)
{ return w(f.get()); }, move(f), move(w));
}
template <typename Work>
auto then(future<void> f, Work w) -> future<decltype(w())>
{
return async([](future<void> f, Work w)
{ f.wait(); return w(); }, move(f), move(w));
}
See Question&Answers more detail:os