У меня есть несколько вопросов о реализации функции 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));
}