从中间期货创造未来?

时间:2013-02-14 14:27:38

标签: 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();
};

如何从std::future<Component>转到std::future<Item>


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

3 个答案:

答案 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上测试过)。