从 T 创建 std::future<T> 的最佳方式

问题描述 投票:0回答:3

我正在使用

std::future<T>
来存储可选异步操作的结果。根据函数的参数,操作可以是异步的,也可以是同步的。在同步情况下,我想将一个值存储在
future
中。我怎样才能最好地做到这一点?

https://en.cppreference.com/w/cpp/thread/future中给出的示例是:

  1. future
     来自 
    packaged_task
    
    
  2. future
     来自 
    async()
    
    
  3. future
     来自 
    promise
    
    
但是没有

make_future

future
 构造函数也不允许从值创建 
fulfilled future
。所以我创建了一个辅助函数来做到这一点,通过像这样的 
promise

template <typename T> std::future<T> make_future(T&& t) { std::promise<T> p; p.set_value(std::forward<T>(t)); return p.get_future(); }

这是从

std::future<T>

 创建 
T
 的有效方法吗?

有没有更好的方法从

std::future<T>

 创建 
T

编辑:示例,缓存:

Foo readAndCacheFoo(int id); std::future<Foo> readFooAsync(int id) { { const lock_guard lock{cacheMutex}; if (id == cachedId) { return make_future(cachedFoo); } } return std::async(readAndCacheFoo, id); }
    
c++ c++11 future
3个回答
1
投票
这可以很容易地完成,但有点复杂:

template <typename T> std::future<T> make_future(T&& t) { auto fun = [val=std::forward<T>(t)]() { return val; }; std::packaged_task<T()> task(std::move(fun)); auto future = task.get_future(); task(); return future; }

请注意,

std::future

packaged_task
应该共享内部状态,因此这应该是安全的

编辑: 实际上,您的代码似乎也是有效的,甚至更简单


1
投票
这是从 T 创建 std::future 的有效方法吗?

是的,是的。

但是,我想说“make_future”可能不是最合适的名称。 “未来”类的整体思想是,它的价值可能在未来准备好,而你的函数总是返回一个已经实现的未来。

好吧,这只是一个名字...Afaik,你的逻辑完全没问题。

编辑: 有一个针对

make_ready_future

make_exceptional_future
 函数的 C++ 提案。
P0159R0


0
投票
虽然 @bartop with packaged_task 的答案是绝对正确的,但让我注意现有的 std 函数:

auto my_shine_future = std::async(std::launch::deferred, [...](args..., ){...} ...);

std::launch::deferred

 - 创建惰性评估而不需要额外的线程。

© www.soinside.com 2019 - 2024. All rights reserved.