我有一个函数foo
,返回future
。 foo
将注册一个将在foo
返回后调用的回调。
future<int> foo() {
promise<int> p;
future<int> ret(p.get_future());
thread(bind([] (promise<int> &&p) {
this_thread::sleep_for(chrono::seconds(3));
p.set_value(10);
}, move(p))).detach();
return move(ret);
}
int main()
{
auto f = foo();
cout << f.get() << endl;
return 0;
}
但似乎std::bind
将rvalue引用转发为左值引用,因此无法成功编译。有什么办法可以解决吗?
我必须编写一个丑陋的类来移动promise
对象:
template<typename T>
class promise_forward {
promise<T> promise_;
public:
promise_forward(promise<T> &&p) :
promise_(move(p)) {}
promise_forward(promise_forward<T> &&other) :
promise_(move(other.promise_)) {}
operator promise<T> () {
return move(promise_);
}
};
future<int> foo() {
promise<int> p;
future<int> ret(p.get_future());
thread(bind([] (promise<int> &&p) {
this_thread::sleep_for(chrono::seconds(3));
p.set_value(10);
}, promise_forward<int>(move(p)))).detach();
return ret;
}
int main()
{
auto f = foo();
cout << f.get() << endl;
return 0;
}
答案 0 :(得分:1)
基本上,你在这里不需要std::bind
(好吧,我相信如此=))。
这是一个最简单的异步任务启动器的快速草案。它几乎与你的相同,但是,只是更通用一点:它可以接受任何函数对象,并且它不那么具有侵入性:函数对象根本不了解promises或线程。
可能存在错误(我很确定它们是错误的)。而且,当然,距离std::async
实现(通常不仅仅是线程启动器,但理想情况下,有一个巨大的线程管理后端),它距离很远。
#include <thread>
#include <future>
#include <iostream>
#include <chrono>
template< class Function, class... Args>
std::future<typename std::result_of<Function(Args...)>::type> my_async(Function && f, Args && ... args)
{
typedef typename std::result_of<Function(Args...)>::type ret_type;
std::promise<ret_type> p;
auto fut = p.get_future();
// lambda in separate variable, just to improve readability
auto l = [](Function && f, Args && ... args, std::promise<ret_type> && p)
{
p.set_value(f(args...));
};
std::thread th(l, std::move(f), std::move(args...), std::move(p));
th.detach();
return std::move(fut);
}
int wannaRunAsync(int i)
{
return i;
};
int main()
{
auto fut = my_async(&wannaRunAsync, 42);
auto fut2 = my_async([](int i) -> int { return i; }, 42);
std::cout << fut.get() << std::endl;
std::cout << fut2.get() << std::endl;
std::cin.get();
return 0;
}
我能够编译并运行它 g++-4.8和 clang++但是使用msvc 2012和2013预览它甚至不会编译(可能是由于错误)。
我根本没有测试过这段代码,所以要小心=)希望它有所帮助。