“扁平”嵌套期货

时间:2012-02-17 21:08:23

标签: c++ boost c++11 boost-thread future

我有一个辅助函数,用于将嵌套的期货“扁平化”为单一的未来:

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

我正在使用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();

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

1 个答案:

答案 0 :(得分:2)

(注意:我不明白你如何boost::unique_futurestd::async合作,所以我用boost::unique_future替换了std::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>,那么我可能会调用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)...));
}