I'm trying to get the code from this post to work with Visual Studio 2013. My current version is below and works fine with gcc and clang (coliru demo).
The standard says about std::async in 30.6.8.2:
Requires: F and each Ti in Args shall satisfy the MoveConstructible requirements.
But the standard library from MSVC seems to try to copy the functor object, which will obviously not work because of the std::future member.
My current workaround is the commented out copy constructor that does evil stuff, but maybe a reference object would be a better workaround.
Is my code incorrect or does VS have a bug there? Is there a better workaround if this is a bug?
#ifndef CONTINUATION_H
#define CONTINUATION_H
#include <future>
namespace detail {
template<typename F, typename W, typename R>
struct helper
{
F f;
W w;
helper(F f, W w)
: f(std::move(f))
, w(std::move(w))
{
}
/*helper(const helper& other)
: f(std::move(const_cast<helper&>(other).f))
, w(other.w)
{
}*/
helper(helper&& other)
: f(std::move(other.f))
, w(std::move(other.w))
{
}
helper& operator=(helper other)
{
f = std::move(other.f);
w = std::move(other.w);
return *this;
}
R operator()()
{
f.wait();
return w(std::move(f));
}
};
}
namespace util
{
template<typename F, typename W>
auto then(F f, W w) -> std::future<decltype(w(std::move(f)))>
{
return std::async(std::launch::async, detail::helper<F, W, decltype(w(std::move(f)))>(std::move(f), std::move(w)));
}
}
#endif
int main()
{
std::promise<int> prom;
auto fut = prom.get_future();
std::thread th([&](){
prom.set_value(42);
});
util::then(std::move(fut), [](std::future<int> f){
printf("future got: %i\n", f.get());
});
th.join();
}