如何创建一个带参数的packaged_task
How do I create a packaged_task with parameters?
学习了这个关于期货、承诺和打包任务的优秀教程后,我想要准备我自己的任务
#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 };
嗯…是我的问题,还是β -gcc的问题?
首先,如果您声明std::packaged_task
接受参数,那么您必须将它们传递给operator()
,而不是构造函数。在一个线程中,你可以这样做:
std::packaged_task<int(int,int)> task(&ackermann);
auto f=task.get_future();
task(3,11);
std::cout<<f.get()<<std::endl;
要对线程执行相同的操作,您必须将任务移到线程中,并传递参数:
std::packaged_task<int(int,int)> task(&ackermann);
auto f=task.get_future();
std::thread t(std::move(task),3,11);
t.join();
std::cout<<f.get()<<std::endl;
或者,您可以在构造任务之前直接绑定参数,在这种情况下,任务本身现在有一个不接受参数的签名:
std::packaged_task<int()> task(std::bind(&ackermann,3,11));
auto f=task.get_future();
task();
std::cout<<f.get()<<std::endl;
同样,您可以这样做并将其传递给线程:
std::packaged_task<int()> task(std::bind(&ackermann,3,11));
auto f=task.get_future();
std::thread t(std::move(task));
t.join();
std::cout<<f.get()<<std::endl;
所有这些示例都应该可以工作(并且使用g++ 4.6和MSVC2010以及我的线程库的just::thread实现)。如果没有,那么您正在使用的编译器或库中存在错误。例如,随g++ 4.6附带的库不能处理传递仅移动对象,如std::packaged_task
到std::thread
(因此无法处理第二个和第四个例子),因为它使用std::bind
作为实现细节,而std::bind
的实现错误地要求参数是可复制的。
由于您在没有参数的情况下启动线程,因此您希望在没有参数的情况下启动任务,就像使用了task1()
一样。因此,您希望支持的签名不是int(int, int)
,而是int()
。反过来,这意味着必须将与该签名兼容的函子传递给std::packaged_task<int()>
的构造函数。试一试:
packaged_task<int()> task1 { std::bind(&ackermann, 3, 11) };
packaged_task<int(int,int)> task1 { &ackermann };
auto f1 = task1.get_future();
thread th1 { move(task1), 3, 11 };
,因为std::thread
的构造函数可以接受参数。在这里,传递给它的函子将像使用task1(3, 11)
一样使用。
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 使用指向成员的指针将成员函数作为参数传递
- 没有名称的C++模板参数