gpt4 book ai didi

c++ - 如何创建带参数的 packaged_task?

转载 作者:可可西里 更新时间:2023-11-01 17:08:19 25 4
gpt4 key购买 nike

正在关注 this excellent tutorial对于futurespromises打包任务,我到了要准备自己的任务的地步

#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?

最佳答案

首先,如果您声明 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;

或者,您可以在构造任务之前直接绑定(bind)参数,在这种情况下,任务本身现在有一个不带参数的签名:

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(因此无法处理第二个和第 4 个示例),因为它使用 std::bind 作为实现细节,而 std::bind 的实现错误地要求参数是可复制的。

关于c++ - 如何创建带参数的 packaged_task?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7548480/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com