Я хочу использовать .net’s System.Threading.Tasks.Task.ContinueWith
в C ++, поэтому я пишу следующую функцию ..
#include <iostream>
#include <functional>
#include <future>
template <typename Func, typename Ret>
auto continue_with(std::future<Ret> &&fu, Func func)
-> std::future<decltype(func(fu.get()))>
{
return std::async(
[fu = std::move(fu), func]() mutable { return func(fu.get()); }
);
}
template <typename Func>
auto continue_with(std::future<void> &&fu, Func func)
-> std::future<decltype(func())>
{
return std::async(
[fu = std::move(fu), func]() mutable { fu.get(); return func(); }
);
}
int main()
{
std::future<void> fu = std::async([]{ std::cout << "fu" << std::endl; });
std::future<void> fu2 = continue_with(
std::move(fu),
[]{ std::cout << "fu2" << std::endl; }
);
fu2.get();
std::cout << "fu continue complete" << std::endl;
std::future<int> retfu = std::async([]{ std::cout << "retfu" << std::endl; return 3; });
std::future<int> retfu2 = continue_with(
std::move(retfu),
[](int result){ std::cout << "retfu2 " << result << std::endl; return result + 1; }
);
int ret = retfu2.get();
std::cout << "retfu continue complete : " << ret << std::endl;
std::cin.get();
}
Этот код работает на GCC 4.8.2 с -std=c++1y
, (Я не знаю почему, но это работает с -std=c++11
, тоже)
Но это не работает на VC ++ 2013. Я думаю, это потому, что init-capture — функция C ++ 14. Как я могу запустить этот код с VC ++ 2013?
(Я хочу использовать лямбду, поэтому, пожалуйста, не говорите мне «используйте только структуру объекта-функции!»)
(Я старался Переместить захват в лямбду, но это не работает ..)
(Буду признателен, если вы не только ответите на мой вопрос, но и улучшите мой код)
К сожалению, эта функция еще не присутствовала в Visual Studio 2013. Она была выпущена в июне 2014 года с Visual Studio «14» ОСАГО (предварительный просмотр сообщества, который имеет альфа-качество и не готов к производству кода). Цитировать:
Вот улучшения для Visual C ++:
Обобщенный лямбда-захват: вы можете назначить результат оценки
Выражение переменной в предложении захвата лямбды. это
позволяет экземпляр Тип перемещения только для захвата по значению.
Как было отмечено в комментариях: в качестве обходного пути для Visual Studio 2013 вы можете создать свой собственный объект функции с локальными переменными, инициализированными через конструктор. Да, это отстой, но это был стандартный прием до того, как были изобретены лямбды. Это также имело место с полиморфными лямбдами, пока они не были поддержаны (обходной путь: объект функции с шаблонным operator()
) и в настоящее время с в настоящее время запрещено constexpr
лямбда (обходной путь: constexpr
функциональный объект литерального типа).
Существуют 2 другие опции, использующие std :: bind и записывающие ход в оболочку копирования.
чтобы ты мог сделать
return std::async(std::bind(
[func](std::future<void> & fu) mutable { fu.get(); return func(); },
std::move(fu)
);
Переход на копию оболочки, я могу просто указать вам Как захватить std :: unique_ptr "на ходу" для лямбды в std :: for_each