我正在编写一些多线程代码并使用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)以使其无论如何都有效.