如何将标准::未来<T>转换为标准::未来<void>?
How to convert std::future<T> to std::future<void>?
我遇到这样一种情况:调用 API A 会导致std::future<some_type>
,但需要向 API B 提供std::future<void>
:
std::future<some_type> api_a();
void api_b(std::future<void>& depend_on_this_event);
在没有建议的功能(如.then()
或when_all()
)的情况下,是否有任何有效的方法可以抛弃附加到std::future<T>
的价值,只留下代表事件完成的基础std::future<void>
?
类似以下内容的方法可能有效,但可能效率低下:
auto f = api_a();
f.wait();
auto void_f = std::async(std::launch::defer, []{});
api_b(void_f);
你能得到的最好的可能是这个:
auto f = api_a();
auto void_f = std::async(std::launch::deferred,[fut = std::move(f)]{ fut.wait();});
api_b(void_f);
template<class U>
struct convert_future_t {
template<class T>
std::future<U> operator()( std::future<T>&& f ) const {
return std::async(std::launch::deferred,
[f=std::move(f)]()->U{ return f.get(); }
);
}
}
template<>
struct convert_future_t<void> {
template<class T>
std::future<void> operator()( std::future<T>&& f ) const {
return std::async(std::launch::deferred,
[f=std::move(f)]()->void{ f.get(); }
);
}
}
template<class U, class T>
std::future<U> convert_future( std::future<T>&& f ) {
return convert_future_t<U>{}(std::move(f));
}
这是@sbabbi答案的通用版本。
api_b( convert_future<void>( api_a() ) );
这允许任何目标和目标类型透明地工作。
这种方法的最大缺点是,由此产生的未来是一个延迟的未来,包装了一个(可能是异步的)未来,这意味着.wait_for()
和.ready()
API 不像异步期货那样工作。 返回的未来永远不会准备好,直到等待。
因此,我们可以稍微改进这一点:
template<class T>
struct ready_future_t {
template<class...Us>
std::future<T> operator()( Us&&...us ) const {
std::promise<T> p;
p.set_value(T(std::forward<Us>(us)...));
return p.get_future();
}
};
template<>
struct ready_future_t<void> {
using T=void;
// throws away the Us&&...s
template<class...Us>
std::future<T> operator()( Us&&...us ) const {
std::promise<T> p;
p.set_value();
return p.get_future();
}
};
template<class T, class...Us>
std::future<T> ready_future(Us&&...us){
return ready_future_t<T>{}(std::forward<Us>(us)...);
}
template<class U>
struct convert_future_t {
template<class T>
std::future<U> operator()( std::future<T>&& f ) const {
if (f.wait_for(0ms)==std::future_status::ready)
return ready_future<U>(f.get());
return std::async(std::launch::deferred,
[f=std::move(f)]()->U{ return f.get(); }
);
}
};
template<>
struct convert_future_t<void> {
template<class T>
std::future<void> operator()( std::future<T>&& f ) const {
if (f.wait_for(0ms)==std::future_status::ready)
return ready_future<void>();
return std::async(std::launch::deferred,
[f=std::move(f)]()->void{ f.get(); }
);
}
};
至少如果我们转换它时未来已经准备好了,那么返回的未来也准备好了。
现场示例
相关文章:
- 在Linux中哪里可以找到互斥、未来等的源代码
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- EASTL矢量<向量<int>>连续的
- 使用 std::string () const 函数启动线程或未来
- QVTKWidget在VTK 8.1中已弃用,并将在未来的版本中删除
- 如何在不设置值的情况下通知 c++ 未来?
- C++ 未解析的标识符未来
- 未来值公式显示疯狂巨大数字的输出
- 未来由函数返回
- 函数范围的静态变量如何导致与共享库中函数代码的未来使用不兼容
- 无法调用未来::获取存储在地图中的未来
- 未来C++标准支持"Declaring type template parameters with auto"
- 是否有一些东西限制了未来引入多个返回值C++标准?
- 为什么是标准::未来不阻塞
- C++发布版本中的未来错误值
- 为什么C++线程/未来开销如此之大
- 从标准::未来<void>到非标量标准::未来<bool>引发的错误转换
- 自动(toCast)显式转换是否计划在未来C++标准?
- 如何在不引入未来对象切片的情况下实现 ICloneable
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ