C++ 如何使用参数创建打包的_任务?

C++ 如何使用参数创建打包的_任务?,c++,c++11,future,packaged-task,C++,C++11,Future,Packaged 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, acker

跟随未来、承诺和打包任务,我达到了我想要准备自己任务的地步

#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();
}

嗯。。。是我,还是beta gcc?

因为您在启动线程时没有参数,所以您希望任务在启动时没有参数,就像使用了
task1()
一样。因此,您想要支持的签名不是
int(int,int)
,而是
int()
。反过来,这意味着您必须将与此签名兼容的函子传递给
std::packaged_task
的构造函数。尝试:

packaged_task<int()> task1 { std::bind(&ackermann, 3, 11) };
packated_任务task1{std::bind(&ackermann,3,11)};
另一种可能性是:

packaged_task<int(int,int)> task1 { &ackermann };
auto f1 = task1.get_future();
thread th1 { move(task1), 3, 11 };
packated_任务task1{&ackermann};
自动f1=task1.get_future();
线程th1{move(task1),3,11};

因为
std::thread
的构造函数可以接受参数。在这里,您传递给它的函子将被当作使用了
task1(3,11)
一样使用。

首先,如果您声明
std::packaged_task
接受参数,那么您必须将它们传递给
操作符()
,而不是构造函数。因此,在单个线程中,您可以执行以下操作:

std::packaged_task<int(int,int)> task(&ackermann);
auto f=task.get_future();
task(3,11);
std::cout<<f.get()<<std::endl;
std::打包的任务(&ackermann);
自动f=任务。获取未来();
任务(3,11);

标准::cout@towi对什么说“不”?又是编译错误?错误是什么?是的,不同的错误。我认为我得到的最接近(最短的错误列表)是:
packaged_任务task1(bind(ack,3,11));线程th1{move(task1)}有错误:
元组:274:17:error:'constexpr std:\u元组_impl@towi我可以用GCC4.7的快照重现我的错误。由于在执行例如
std::make_tuple(std::packaged_task{})时出现问题
我认为这是
std::tuple
实现中的一个错误(错误也非常明显)。我认为编写一个函子不会有多大帮助,将
std::packaged_任务
传递给
std::bind
std::thread
现在是有问题的。谢谢。我也有上星期的svn快照。我现在就把它放在那里,大约一个月后再谈。你不觉得版本
pkg吗_task@towi我没有看到合适的构造函数使其有效,您仍然希望签名是
int()
,而不是
int(int,int)
。另外,我必须提醒你,几个月前我就开始学习自己的
std::packaged_task
-类课程,因为那时已经有问题了。现在还不知道什么时候会起作用。看看
std::bind
的要求,参数要求是可复制的并不是真的。段落太长,无法粘贴到此处,它是20.8.9.1.2函数模板绑定[func.bind.bind]段落5。实际的要求是存储的类型可以移动,并且可以从传递的参数构造。尽管我确实记得GCC附带的一个错误实现,它确实需要可复制的。(但这不是OP面临的问题。)代码工作正常,但我在
std::unique_lock l(td.m)一行中有一个问题当线程检查条件变量时,线程中的互斥锁是否已经锁定?我想我错过了一些东西。我认为它会将互斥锁锁定在线程中,然后等待停止标志或将工作添加到队列中。在这种情况下,主线程不会一直等待锁被释放吗?这是因为一个虚假的唤醒才起作用吗?@bjackfly:我不确定你指的是哪一个代码,但条件变量wait在等待期间解锁互斥锁,然后在唤醒时重新锁定,然后再检查谓词。谢谢@AnthonyWilliams我没有看到我现在指的代码,一定是同时看了几篇文章,然后贴出了对这篇文章的回应,可能是错误的。不过,这个答案有帮助。顺便说一句,我喜欢这本书真的很棒。
packaged_task<int(int,int)> task1 { &ackermann };
auto f1 = task1.get_future();
thread th1 { move(task1), 3, 11 };
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;