У меня есть несколько вопросов о реализации функции then() в Обсуждение Herb Sutter. Эта функция используется для цепочки асинхронных операций, параметр f - это будущее от одной операции, а параметр w - это "работа" для этой операции (лямбда).
template <typename Fut, typename Work>
auto then(Fut f, Work w) -> future<decltype(w(f.get()))>
{
return async([=]{ w(f.get()); });
}
Примером приложения может быть:
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;
});
Основной поток запускает задачи, но не дожидается завершения любого из них.
Во-первых, future<T> не имеет конструктора копирования. Это означает, что предлагаемая реализация может использоваться только с shared_future<T>, если мы не изменим вызов на async(), чтобы переместить будущее в лямбда. Этот вопрос SO предложил способ сделать это, но это кажется слишком сложным. Я повторно выполнил эту функцию, и мне интересно, правильно ли мой код или я что-то пропустил...
Во-вторых, будущее, которое передается функции then(), может быть void, поэтому нам действительно нужны 2 реализации then(), правильно? Один для фьючерсов, возвращающих T, и один для фьючерсов, возвращающих void.
Наконец, если лямбда внутри тела then() не имеет оператора возврата, чтобы мы могли вернуть значение обратно? Без оператора return возвращается future<void>, правильно?
Я попытался решить вышеуказанные моменты, и это то, что я придумал. Правильно ли это?
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));
}