如何创建带有参数的packaged_task?
遵循这个关于期货的优秀教程 /em>、承诺和打包任务我已经到了想要准备自己的任务的程度,
#include <iostream>
#include <future>
using namespace std;
int ackermann(int m, int n) { // might take a while
if(m==0) return n+1;
if(n==0) return ackermann(m-1,1);
return ackermann(m-1, ackermann(m, n-1));
}
int main () {
packaged_task<int(int,int)> task1 { &ackermann, 3, 11 }; // <- error
auto f1 = task1.get_future();
thread th1 { move(task1) }; // call
cout << " ack(3,11):" << f1.get() << endl;
th1.join();
}
据我所知, gcc-4.7.0 错误消息它期望参数不同吗?但如何呢?我尝试缩短错误消息:
error: no matching function for call to
'std::packaged_task<int(int, int)>::packaged_task(<brace-enclosed initializer list>)'
note: candidates are:
std::packaged_task<_Res(_ArgTypes ...)>::---<_Res(_ArgTypes ...)>&&) ---
note: candidate expects 1 argument, 3 provided
...
note: cannot convert 'ackermann'
(type 'int (*)(int, int)') to type 'std::allocator_arg_t'
我为ackermann
提供参数的变体是否错误?或者是错误的模板参数?我没有给线程的创建参数3,11
,对吧?
更新其他不成功的变体:
packaged_task<int()> task1 ( []{return ackermann(3,11);} );
thread th1 { move(task1) };
packaged_task<int()> task1 ( bind(&ackermann,3,11) );
thread th1 { move(task1) };
packaged_task<int(int,int)> task1 ( &ackermann );
thread th1 { move(task1), 3,11 };
嗯...是我,还是beta-gcc?
Following this excellent tutorial for futures, promises and packaged tasks I got to the the point where I wanted to prepare my own task
#include <iostream>
#include <future>
using namespace std;
int ackermann(int m, int n) { // might take a while
if(m==0) return n+1;
if(n==0) return ackermann(m-1,1);
return ackermann(m-1, ackermann(m, n-1));
}
int main () {
packaged_task<int(int,int)> task1 { &ackermann, 3, 11 }; // <- error
auto f1 = task1.get_future();
thread th1 { move(task1) }; // call
cout << " ack(3,11):" << f1.get() << endl;
th1.join();
}
As far as I can decipher the gcc-4.7.0 error message it expects the arguments differently? But how? I try to shorten the error message:
error: no matching function for call to
'std::packaged_task<int(int, int)>::packaged_task(<brace-enclosed initializer list>)'
note: candidates are:
std::packaged_task<_Res(_ArgTypes ...)>::---<_Res(_ArgTypes ...)>&&) ---
note: candidate expects 1 argument, 3 provided
...
note: cannot convert 'ackermann'
(type 'int (*)(int, int)') to type 'std::allocator_arg_t'
Is my variant how I provide the parameters for ackermann
wrong? Or is it the wrong template parameter? I do not give the parameters 3,11
to the creation of thread, right?
Update other unsuccessful variants:
packaged_task<int()> task1 ( []{return ackermann(3,11);} );
thread th1 { move(task1) };
packaged_task<int()> task1 ( bind(&ackermann,3,11) );
thread th1 { move(task1) };
packaged_task<int(int,int)> task1 ( &ackermann );
thread th1 { move(task1), 3,11 };
hmm... is it me, or is it the beta-gcc?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,如果您声明
std::packaged_task
来接受参数,那么您必须将它们传递给operator()
,而不是构造函数。在单个线程中,您可以这样做:要对线程执行相同的操作,您必须将任务移动到线程中,并传递参数:
或者,您可以在构造之前直接绑定参数任务,在这种情况下,任务本身现在有一个不带参数的签名:
同样,您可以执行此操作并将其传递给线程:
所有这些示例都应该有效(并且对于 g++ 4.6 和 MSVC2010 以及我的 <一个href="http://www.stdthread.co.uk" rel="noreferrer">只是::thread 线程库的实现)。如果没有,那么您正在使用的编译器或库中存在错误。例如,g++ 4.6 附带的库无法处理将仅移动对象(例如
std::packaged_task
)传递到std::thread
(因此无法处理第二个和第四个示例),因为它使用 std::bind 作为实现细节,并且 std::bind 的实现错误地要求参数是可复制的。Firstly, if you declare
std::packaged_task
to take arguments, then you must pass them tooperator()
, not the constructor. In a single thread you can thus do:To do the same with a thread, you must move the task into the thread, and pass the arguments too:
Alternatively, you can bind the arguments directly before you construct the task, in which case the task itself now has a signature that takes no arguments:
Again, you can do this and pass it to a thread:
All of these examples should work (and do, with both g++ 4.6 and MSVC2010 and my just::thread implementation of the thread library). If any do not then there is a bug in the compiler or library you are using. For example, the library shipped with g++ 4.6 cannot handle passing move-only objects such as a
std::packaged_task
tostd::thread
(and thus fails to handle the 2nd and 4th examples), since it usesstd::bind
as an implementation detail, and that implementation ofstd::bind
incorrectly requires that the arguments are copyable.由于您在不带参数的情况下启动线程,因此您希望任务在不带参数的情况下启动,就像使用
task1()
一样。因此,您想要支持的签名不是int(int, int)
而是int()
。反过来,这意味着您必须将与此签名兼容的函子传递给std::packaged_task
的构造函数。尝试:另一种可能是:
因为
std::thread
的构造函数可以接受参数。在这里,您传递给它的函子将像使用task1(3, 11)
一样使用。Since you're starting the thread with no arguments, you expect the task to be started with no arguments, as if
task1()
were used. Hence the signature that you want to support is notint(int, int)
butint()
. In turn, this means that you must pass a functor that is compatible with this signature to the constructor ofstd::packaged_task<int()>
. Try:Another possibility is:
because the constructor of
std::thread
can accept arguments. Here, the functor you pass to it will be used as iftask1(3, 11)
were used.