在以下示例代码中,我想从Item
创建一个Component
对象:
struct Component { };
struct Item {
explicit Item(Component component) : comp(component) {}
Component comp;
};
struct Factory {
static std::future<Item> get_item() {
std::future<Component> component = get_component();
// how to get a std::future<Item> ?
}
std::future<Component> get_component();
};
如何从std::future<Component>
转到std::future<Item>
?
更新:从问题中删除了我的第一个想法(基于线程)并发布了答案。
答案 0 :(得分:13)
需要moar packaged_tasks!
std::future<Item> get_item() {
std::packaged_task<Item()> task([]{
return Item(get_component().get());
});
auto future = task.get_future();
std::thread(std::move(task)).detach();
return future;
};
一般情况下,我建议先忘记承诺并考虑打包_tasks。 packaged_task
负责为您维护(功能,承诺,未来)三元组。它允许您以自然的方式编写函数(即返回和抛出等),并将异常正确地传播到未来,您的示例忽略了这一点(任何线程中的未处理异常{{1你的程序!)。
答案 1 :(得分:3)
我发现我可以将std::async
与延迟启动政策一起使用来撰写最终对象:
std::future<Item> get_item()
{
// start async creation of component
// (using shared_future to make it copyable)
std::shared_future<Component> component = get_component();
// deferred launch policy can be used for construction of the final object
return std::async(std::launch::deferred, [=]() {
return Item(component.get());
});
}
答案 2 :(得分:2)
您还可以使用Herb Sutter提出的then
功能。这是该函数的略微修改版本。有关如何修改的更多信息以及原始谈话的链接可以在this SO question中找到。您的代码将归结为:
return then(std::move(component), [](Component c) { return Item(c); });
最初的想法是将函数then
作为std::future<T>
的成员函数,并且正在进行一些将其纳入标准的工作。该函数的第二个版本用于void
期货(基本上只是异步链接函数)。正如赫伯指出的那样,你可能需要额外的线程来支付使用这种方法的费用。
您的代码如下所示:
#include <future>
#include <thread>
#include <iostream>
template <typename T, typename Work>
auto then(std::future<T> f, Work w) -> std::future<decltype(w(f.get()))>
{
return std::async([](std::future<T> f, Work w)
{ return w(f.get()); }, std::move(f), std::move(w));
}
template <typename Work>
auto then(std::future<void> f, Work w) -> std::future<decltype(w())>
{
return std::async([](std::future<void> f, Work w) -> decltype(w())
{ f.wait(); return w(); }, std::move(f), std::move(w));
}
struct Component { };
struct Item {
Item(Component component) : comp(component) {}
Component comp;
};
struct Factory {
static std::future<Item> get_item() {
std::future<Component> component = get_component();
return then(std::move(component), [](Component c) { return Item(c); });
}
static std::future<Component> get_component()
{
return std::async([](){ return Component(); });
}
};
int main(int argc, char** argv)
{
auto f = Factory::get_item();
return 0;
}
上面的代码使用clang和libc ++编译好(在Mac OS X 10.8上测试过)。