从中间期货创造未来?

Sta*_*ked 10 c++ c++11

在下面的示例代码中,我想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();
};
Run Code Online (Sandbox Code Playgroud)

如何从去std::future<Component>std::future<Item>


更新:从问题中删除了我的第一个想法(基于线程)并发布了答案.

R. *_*des 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;
};
Run Code Online (Sandbox Code Playgroud)

一般来说,我建议首先忘记承诺并考虑打包.A packaged_task负责为您维护(功能,承诺,未来)三联.它允许您以自然的方式编写函数(即使用返回和抛出等),并将异常正确地传播到将来,您的示例忽略了(在您的程序的任何线程中未处理的异常std::terminate!).


Sta*_*ked 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());
    });
}
Run Code Online (Sandbox Code Playgroud)