request for member ‘get_future’ in ‘task’, which is of non-class type ‘std::packaged_task<int(__gnu_cxx::__normal_iterator<int*, std::vector<int> >, __gnu_cxx::__normal_iterator<int*, std::vector<int> >)>(accumulate_block<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, int> (*)())’ futures[i]=task.get_future();
时间: 2024-03-15 21:44:02 浏览: 17
这个错误的原因是`task`变量的类型不是一个类类型,因此不能调用`get_future()`函数。在这里,`task`的类型是一个函数类型,它返回一个`std::packaged_task`对象,而不是一个`std::packaged_task`对象本身。
要解决这个错误,需要在创建`std::packaged_task`对象时使用函数类型的别名或函数指针类型。例如,如果要使用函数类型别名`Func`来定义`std::packaged_task`对象,可以这样写:
```c++
using Func = int(std::vector<int>::iterator, std::vector<int>::iterator);
std::packaged_task<Func> task(accumulate_block<int>);
```
或者,使用函数指针类型`FuncPtr`定义`std::packaged_task`对象,可以这样写:
```c++
using FuncPtr = int(*)(std::vector<int>::iterator, std::vector<int>::iterator);
std::packaged_task<FuncPtr> task(&accumulate_block<int>);
```
这样可以确保`task`的类型为`std::packaged_task`,从而可以调用`get_future()`函数获取与任务关联的`std::future`对象。
相关问题
c++std::packaged_task
c++的std::packaged_task是一个模板类,用于在异步操作中封装任务。它将一个可调用对象(例如函数、函数对象、Lambda表达式等)与一个future对象关联起来,使得任务可以异步执行,并获得返回值。
使用std::packaged_task的步骤如下:
1. 创建一个std::packaged_task对象,将可调用对象作为参数传入构造函数中。
2. 调用std::packaged_task的operator()方法来执行任务,也可以通过std::thread等线程库来执行任务。
3. 通过std::packaged_task的get_future()方法获取与之关联的future对象,用于获取任务的返回值。
4. 在需要的地方,通过future对象的get()方法来获取异步任务的返回值。
std::packaged_task的一个主要特点是可以将任务的执行与返回值的获取分开处理,这使得我们可以在需要的时候才去获取返回值,而不必阻塞程序的执行。另外,std::packaged_task还可以与std::thread等线程库结合使用,实现真正的并发执行。
总之,通过使用std::packaged_task,我们可以将一个任务封装起来,并异步执行,同时可以在需要的时候获取返回值。这为编写并发程序提供了更灵活和高效的方式。
#include <vector> #include <queue> #include <thread> #include <mutex> #include <condition_variable> #include <functional> #include <future> class ThreadPool { public: ThreadPool(size_t threads) : stop(false) { for (size_t i = 0; i < threads; ++i) { workers.emplace_back([this] { for (;;) { std::function<void()> task; { std::unique_lockstd::mutex lock(this->queue_mutex); this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); }); if (this->stop && this->tasks.empty()) return; task = std::move(this->tasks.front()); this->tasks.pop(); } task(); } }); } } ~ThreadPool() { { std::unique_lockstd::mutex lock(queue_mutex); stop = true; } condition.notify_all(); for (std::thread &worker : workers) worker.join(); } template<class F, class... Args> auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> { using return_type = typename std::result_of<F(Args...)>::type; auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...)); std::future<return_type> res = task->get_future(); { std_lockstd::mutex lock(queue_mutex); if (stop) throw std::runtime_error("enqueue on stopped ThreadPool"); tasks.emplace([task] { (*task)(); }); } condition.notify_one(); return res; } private: std::vectorstd::thread workers; std::queue<std::function<void()>> tasks; std::mutex queue_mutex; std::condition_variable condition; bool stop; }; 怎么获取结果
可以使用`std::future`来获取线程池中任务的返回值。在`enqueue`函数中,任务被包装在`std::packaged_task`中,这个包装器可以将一个函数包装成一个可调用对象,并且可以使用`std::future`来获取函数的返回值。
在`enqueue`函数中,我们使用`std::make_shared`创建了一个`std::packaged_task`,并将要执行的任务`f`和其参数`args`绑定在一起。然后,我们将这个`std::packaged_task`封装在一个`std::shared_ptr`中,以便可以在其他线程中访问它。
接下来,我们使用`std::future`获取`std::packaged_task`的返回值。`std::future`是一个异步结果的占位符,可以用来检查任务是否已经完成,并且可以获取任务的返回值。
具体地,我们可以在调用`enqueue`函数后,使用返回的`std::future`对象的`get()`函数来获取任务的返回值。`get()`函数会阻塞当前线程,直到任务执行完毕并返回结果。
例如,假设我们要执行一个函数`int add(int x, int y)`,我们可以使用以下方式来获取其结果:
```c++
ThreadPool pool(4); // 创建线程池,有4个线程
// 将任务加入线程池,并获取返回值的future对象
auto result = pool.enqueue(add, 3, 4);
// 等待任务执行完成,并获取返回值
int res = result.get();
std::cout << "3 + 4 = " << res << std::endl;
```
这里的`result.get()`会阻塞当前线程,直到任务执行完毕并返回结果。最后,我们将`res`输出到控制台。