std::async
不仅是一个模板,而且它也是重载的。您不仅需要选择所需的模板,还需要选择重载。
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>);
不幸的是,std::bind
似乎不允许绑定函数采用右值引用。所以光写std::bind(chosen_async, &foo)
还是不行。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 {};
}
我们可以这样说std::bind(chosen_async, make_adv(std::move(&foo)))
,除了一个问题:您不能直接传递std::async
我们的包装对象之一,因此std::result_of<...>
(因此std::bind
)。无法推断chosen_async
会返回什么。所以我们明确声明返回类型:
auto async_bound=
std::bind<std::future<foo_rettype>>(chosen_async,
make_adv(std::forward<foo_type>(&foo)));
做这一切似乎足以让 GCC 高兴,至少:http: //ideone.com/gapLs。
当然,您可以使用 lambda 表达式为自己省去很多麻烦:
auto async_bound=[=]()->std::future<void> {return std::async(&foo);};