“压平”嵌套期货

发布于 2025-01-07 02:12:05 字数 1094 浏览 0 评论 0 原文

我有一个辅助函数,用于将嵌套的 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();

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

I have a helper function which I use to "flatten" nested futures into a single future:

EDIT: Renamed "fold" to "flatten" as suggested.

I'm using the futures from the boost library:

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

It is used like this:

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

The problem is that this only works if I convert the "nested" future into a shared_future. Is there any nice way to get around it? What I would like is something like:

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

int result = future_result.get();

Secondly, I am a bit unsure of the name for the method. Any opinions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冷月断魂刀 2025-01-14 02:12:05

(注意:我不明白你如何让 boost::unique_futurestd::async 配合,所以我替换了 boost::unique_future< 的所有实例/code> 和 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 那么也许我会调用 if flatten_future。或者也许只是展平,因为毕竟它首先只接受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)...));
}

(Note: I don't understand how you got boost::unique_future to cooperate with std::async so I replaced all instances of boost::unique_future with std::future. The code has been tested and works on my end.)

The issue is that lambda expressions either capture by value (which really means capture by copy) or by reference (not applicable here as we want to tie the lifetime of the future to our closure), whereas std::future is move-only. The answer to that is usually std::bind, although in this case std::async has a built-in bind-like functionality:

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

I don't have a good name to recommend I'm afraid. If the template perhaps worked recursively to transform any std::future<std::future<std::future<...std::future<T>...>>> to std::future<T> then perhaps I'd call if flatten_future. Or perhaps simply flatten, since after all it only accepts an std::future in the first place.


Assuming we already have a unary 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)...));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文