10

在以下示例代码中,我想Item从 a 创建一个对象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>


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

4

3 回答 3

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;
};

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

于 2013-02-14T14:36:03.587 回答
3

It occurred to me that I can use std::async with the deferred launch policy to compose the final object:

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());
    });
}
于 2013-05-27T11:23:57.960 回答
2

您也可以使用thenHerb Sutter 提出的功能。这是该函数的略微修改版本。有关如何修改的更多信息以及原始谈话的链接可以在这个 SO question中找到。您的代码将归结为:

return then(std::move(component), [](Component c) { return Item(c); });

最初的想法是将函数then作为成员函数,std::future<T>并且正在进行一些将其放入标准的工作。该函数的第二个版本用于void期货(本质上只是异步链接函数)。正如 Herb 指出的那样,您可能会因为可能需要额外的线程而为使用这种方法付费。

您的代码如下所示:

#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 上测试)。

于 2013-02-15T10:28:56.173 回答