我正在编写一些多线程代码并使用promise/future在不同的线程上调用函数并返回其结果.为了简单起见,我将完全删除线程部分:
template <typename F>
auto blockingCall(F f) -> decltype(f())
{
std::promise<decltype(f())> promise;
// fulfill the promise
promise.set_value(f());
// block until we have a result
return promise.get_future().get();
}
Run Code Online (Sandbox Code Playgroud)
这适用于任何返回非函数的函数void
.获得未来的回报也适用于void
.但如果f
是一个void
函数,我无法履行承诺,因为:
promise.set_value(F()); // 错误:无效使用void表达式
是否有一些聪明的方法在线上设置值void
,或者我是否只需编写一个辅助函数,就像call_set_value(promise, f)
有一个重载std::promise<R>
和std::promise<void>
?
Naw*_*waz 13
是.功能过载是最干净的解决方案:
set(promise, f);
Run Code Online (Sandbox Code Playgroud)
然后实现set
为重载函数,如:
template<typename F, typename R>
void set(std::promise<R> & p, F && f) //handle non-void here
{
p.set_value(f());
}
template<typename F>
void set(std::promise<void> & p, F && f) //handle void here
{
f();
p.set_value();
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*ely 13
A promise
只是一种异步结果提供者.而不是promise
你可以使用packaged_task
包装可调用对象,而std::function
不是调用它,除了调用它使得结果可以通过a future
(当然它处理void
和无效结果之间的差异):
template <typename F>
auto blockingCall(F f) -> decltype(f())
{
std::packaged_task<decltype(f())()> task(std::move(f));
task();
// block until we have a result
return task.get_future().get();
}
Run Code Online (Sandbox Code Playgroud)
NB根据目前的标准,该代码将有一个数据比赛中,如果task()
与task.get_future()
发生在单独的线程(使用一个承诺,以便将原来的),所以你应该叫get_future()
交给任务给其他线程之前.在实践中,它应该在实际实现中是安全的,并且存在库问题(LWG 2412)以使其无论如何都有效.