Intereting Posts
LINK: фатальная ошибка LNK1561: точка входа должна быть определена ERROR IN VC ++ Смежное хранение полиморфных типов Использование локального classа в функции C ++ Быстрая запись данных из C ++ Vector в текстовый файл Есть ли способ запретить использование classа по значению в списке аргументов переменной стиля c? C ++ генерирует предупреждение, когда член classа теневой член classа своего родителя? Работа с enumsми в C / C ++ Связь между лимитом стека и streamами Использование SendMessage для ввода текста в элемент управления редактирования, относящийся к другому процессу как использовать библиотеку / функции c / cpp в android Нет ли встроенного способа вычисления мощности во время компиляции на C ++? Необходимо создать http-сервер с использованием Qt 4.7 в C ++ Цветовой бит-сдвиг в шейдере OpenGL GLSL Есть ли легкий парсерный / парный анализатор данных в C или C ++? array vs vector vs list

Создание будущего из промежуточных фьючерсов?

В следующем примере кода я хочу создать объект Item из Component :

 struct Component { }; struct Item { explicit Item(Component component) : comp(component) {} Component comp; }; struct Factory { static std::future get_item() { std::future component = get_component(); // how to get a std::future ? } std::future get_component(); }; 

Как перейти от std::future к std::future ?

Обновление: удалила мою первую идею (которая была на основе streamов) из вопроса и отправила ответ.

Требуется moar packaged_tasks!

 std::future get_item() { std::packaged_task task([]{ return Item(get_component().get()); }); auto future = task.get_future(); std::thread(std::move(task)).detach(); return future; }; 

В общем, я рекомендую забыть о обещаниях и сначала рассмотреть packaged_tasks. packaged_task заботится о том, чтобы поддерживать (функцию, promise, будущее) тройку для вас. Он позволяет вам писать функцию естественным образом (т. Е. С возвратами и бросками и т. Д.) И правильно распространять исключения в будущем, которые ваш пример игнорировал (необработанные исключения в любом streamе std::terminate вашу программу!).

Мне пришло в голову, что я могу использовать std::async с отложенной политикой запуска для создания конечного объекта:

 std::future get_item() { // start async creation of component // (using shared_future to make it copyable) std::shared_future 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()); }); } 

Вы также можете использовать функцию then предложенную Herb Sutter. Вот немного измененная версия функции. Более подробная информация о том, как она была изменена, и ссылка на исходный разговор можно найти в этом вопросе SO . Ваш код будет сводиться к:

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

Первоначальная идея состоит в том, чтобы функция then как функция-член std::future и есть некоторая работа по ее внедрению в стандарт. Вторая версия функции – для фьючерсов void (по сути, просто асинхронно цепочки). Как отметил Герб, вы можете заплатить за использование этого подхода, потенциально нуждаясь в дополнительной теме.

Ваш код будет выглядеть так:

 #include  #include  #include  template  auto then(std::future f, Work w) -> std::future { return std::async([](std::future f, Work w) { return w(f.get()); }, std::move(f), std::move(w)); } template  auto then(std::future f, Work w) -> std::future { return std::async([](std::future 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 get_item() { std::future component = get_component(); return then(std::move(component), [](Component c) { return Item(c); }); } static std::future 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).