std::async
is not only a template, but it's also overloaded. You'll need to select not only the template you want, but also the overload.
typedef decltype(&foo) foo_type;
typedef std::result_of<foo_type()>::type foo_rettype;
auto chosen_async=
static_cast<std::future<foo_rettype> (*)(foo_type && )>
(&std::async<foo_type>);
Unfortunately, std::bind
doesn't seem to allow binding functions taking rvalue references. So just writing std::bind(chosen_async, &foo)
still won't work. A workaround for this problem is discussed in Is there a reference_wrapper<> for rvalue references?:
template<typename T> struct adv {
T t;
explicit adv(T &&t):t(std::forward<T>(t)) {}
template<typename ...U> T &&operator()(U &&...) {
return std::forward<T>(t);
}
};
template<typename T> adv<T> make_adv(T &&t) {
return adv<T>{std::forward<T>(t)};
}
namespace std {
template<typename T>
struct is_bind_expression< adv<T> > : std::true_type {};
}
We'd be done by saying std::bind(chosen_async, make_adv(std::move(&foo)))
, except for one problem: You can't directly pass std::async
one of our wrapper objects, and consequently std::result_of<...>
(hence std::bind
). can't deduce what chosen_async
will return. So we explicitly state the return type:
auto async_bound=
std::bind<std::future<foo_rettype>>(chosen_async,
make_adv(std::forward<foo_type>(&foo)));
Doing all of this seems enough to make GCC happy, at least: http://ideone.com/gapLs.
Of course, you could save yourself a ton of hassle with a lambda expression:
auto async_bound=[=]()->std::future<void> {return std::async(&foo);};