我有一个辅助函数,用于将嵌套的 future“展平”为单个 future:
编辑:按照建议将“fold ”重命名为“展平”。
我正在使用 boost 库中的 futures:
template<typename T>
auto flatten(boost::unique_future<T>&& f) -> boost::unique_future<decltype(f.get().get())>
{
auto shared_f = boost::shared_future<T>(std::move(f));
return async(launch_policy::deferred, [=]() mutable
{
return shared_f.get().get();
});
}
它的用法如下:
auto nested_future_result = async([]() -> boost::shared_future<int>
{
auto tmp = async([]
{
return 1;
});
return boost::shared_future<int>(std::move(tmp));
});
boost::unique_future<int> future_result = flatten(nested_future_result);
int result = future_result.get();
问题是,只有当我将“嵌套” future 转换为shared_future
时,这才有效。有什么好的方法可以绕过它吗?我想要的是这样的:
auto future_result = flatten(async([]
{
return async([]
{
return 1;
});
}));
int result = future_result.get();
其次,我有点不确定该方法的名称。有意见吗?
最佳答案
(注意:我不明白你是如何让 boost::unique_future
与 std::async
合作的,所以我用 boost::unique_future
替换了 std::future
的所有实例。代码已经过测试并且可以在我这边工作。)
问题是 lambda 表达式要么按值捕获(这实际上意味着通过复制捕获),要么按引用捕获(此处不适用,因为我们希望将 future 的生命周期与我们的闭包联系起来),而 std::future
是只能移动的。答案通常是 std::bind
,尽管在本例中 std::async
有一个内置bind
类似功能:
template<typename T>
auto fold(std::future<T>&& f)
-> std::future<decltype(f.get().get())>
{
return std::async(std::launch::deferred, [](std::future<T>&& f)
{
return f.get().get();
}, std::move(f));
}
恐怕我没有好名字可以推荐。如果模板可能递归地工作来转换任何 std::future<std::future<std::future<...std::future<T>...>>>
至std::future<T>
那么也许我会调用 flatten_future
。或者也许只是flatten
,因为毕竟它只接受 std::future
首先。
假设我们已经有一元 async
:
template<typename Functor, typename Arg, typename... Args>
auto async(Functor&& functor, Arg&& arg, Args&&.... args)
-> decltype( async(std::bind(std::forward<Functor>(functor)
, std::forward<Arg>(arg), std::forward<Args>(args)...)) )
{
return async(std::bind(std::forward<Functor>(functor)
, std::forward<Arg>(arg), std::forward<Args>(args)...));
}
关于c++ - "Flatten"嵌套 future ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9335420/