std::async 对比 std::promise
std::async vs std::promise
我必须将 getter 函数包装到 std::future
对象中。
std::function<String (String)>
-> std::function<std::future<String> (String)>
如此简单的问题,最好/最快的方法是什么?
这是我想到的两个选项。
我有一个功能:
std::function<String (String)> getter;
然后使用 std::promise
:
包装它
std::function<std::future<String> (String)> binding = [getter](String context) {
std::promise<String> p;
p.set_value(getter(contex));
return p.get_future();
};
或使用std::async
:
std::function<std::future<String> (String)> binding = [getter](String context) {
return std::async(std::launch::deferred, getter, contex);
};
正确答案是自己写 make_ready_future
(直接从 std::experimantal
中写出来)。 std::promise
是我所知道的产生现成未来的唯一方法:async
产生非现成未来。
这需要一个值,并产生该值的未来,其中包含一些涉及引用包装器的奇特内容(您可以选择跳过)。
存在将其添加到 C++1z 中的提议,因此通过基于其接口构建您自己的版本,您可以使您的代码半符合未来要求。另外,作为一个经过审核的设计,它会比你自己的设计更糟糕。
写完后:
template<class F>
auto futuristic_wrapper( F&& f ) {
return [f=std::forward<F>(f)](auto&&...args){
return make_ready_future( f( decltype(args)(args)... ) );
};
}
在 C++11 中你必须写一个 class 来替换 lambda:
template<class F>
struct futurize {
F f;
template<class...Args>
operator()(Args&&...args)const->
delctype(make_ready_future(f(std::forward<Args>(args)...)))
{ return make_ready_future(f(std::forward<Args>(args)...)); }
};
template<class F>
auto futuristic_wrapper( F&& f )->
futurize< typename std::decay_t<F>::type >
{
return {std::forward<F>(f)};
}
这很烦人,但主要是机械转换。
这实际上不会产生 std::function< future<R>(Args...) >
,但它会 return 可以转换成那个。如果我们根本不需要,则无需键入擦除。
你可以把你从 std::experimantal
偷来的 "your own version of to-be-standardized stuff" 放在像 notstd
这样的命名空间中。始终将它与 notstd::
一起使用(永远不要 using namespace notstd;
,而不是 using notstd::make_ready_future;
,因为当将类型添加到 std
时,风险行为会发生变化),以便以后的用户清楚这是不是这些对象的标准版本。
我必须将 getter 函数包装到 std::future
对象中。
std::function<String (String)>
-> std::function<std::future<String> (String)>
如此简单的问题,最好/最快的方法是什么?
这是我想到的两个选项。
我有一个功能:
std::function<String (String)> getter;
然后使用 std::promise
:
std::function<std::future<String> (String)> binding = [getter](String context) {
std::promise<String> p;
p.set_value(getter(contex));
return p.get_future();
};
或使用std::async
:
std::function<std::future<String> (String)> binding = [getter](String context) {
return std::async(std::launch::deferred, getter, contex);
};
正确答案是自己写 make_ready_future
(直接从 std::experimantal
中写出来)。 std::promise
是我所知道的产生现成未来的唯一方法:async
产生非现成未来。
这需要一个值,并产生该值的未来,其中包含一些涉及引用包装器的奇特内容(您可以选择跳过)。
存在将其添加到 C++1z 中的提议,因此通过基于其接口构建您自己的版本,您可以使您的代码半符合未来要求。另外,作为一个经过审核的设计,它会比你自己的设计更糟糕。
写完后:
template<class F>
auto futuristic_wrapper( F&& f ) {
return [f=std::forward<F>(f)](auto&&...args){
return make_ready_future( f( decltype(args)(args)... ) );
};
}
在 C++11 中你必须写一个 class 来替换 lambda:
template<class F>
struct futurize {
F f;
template<class...Args>
operator()(Args&&...args)const->
delctype(make_ready_future(f(std::forward<Args>(args)...)))
{ return make_ready_future(f(std::forward<Args>(args)...)); }
};
template<class F>
auto futuristic_wrapper( F&& f )->
futurize< typename std::decay_t<F>::type >
{
return {std::forward<F>(f)};
}
这很烦人,但主要是机械转换。
这实际上不会产生 std::function< future<R>(Args...) >
,但它会 return 可以转换成那个。如果我们根本不需要,则无需键入擦除。
你可以把你从 std::experimantal
偷来的 "your own version of to-be-standardized stuff" 放在像 notstd
这样的命名空间中。始终将它与 notstd::
一起使用(永远不要 using namespace notstd;
,而不是 using notstd::make_ready_future;
,因为当将类型添加到 std
时,风险行为会发生变化),以便以后的用户清楚这是不是这些对象的标准版本。