2

我有一个辅助函数,我用它来将嵌套的期货“展平”成一个单一的期货:

编辑:按照建议将“折叠”重命名为“展平”。

我正在使用来自 boost 库的期货:

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();

问题是,这仅在我将“嵌套”未来转换为shared_future. 有什么好办法绕过它吗?我想要的是这样的:

auto future_result = flatten(async([]
{
    return async([]
    {
        return 1;
    }); 
}));

int result = future_result.get();

其次,我有点不确定该方法的名称。有什么意见吗?

4

1 回答 1

2

(注意:我不明白你是如何boost::unique_future合作的,所以我用std::async替换了所有实例。代码已经过测试,可以在我这边工作。)boost::unique_futurestd::future

问题是 lambda 表达式要么按值捕获(这实际上意味着按副本捕获),要么按引用捕获(此处不适用,因为我们希望将未来的生命周期与闭包联系起来),而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>那么我可能会调用 if flatten_future。或者也许很简单flatten,因为毕竟它首先只接受 a 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)...));
}
于 2012-02-18T02:48:50.143 回答