[静态声明失败,尝试使用std :: vector

问题描述 投票:0回答:1

我有下面的类,它是头文件。当我在std::vector<std::thread> threads;中包含行ProducerManager.h时,出现此问题底部显示的错误。我经历了多个SO问题,这些问题不是使用std :: move()将线程移动到向量中的,但是,显然,因为我通过rvalue进行处理应该可以工作。但是我收到了一个我不明白的奇怪错误。有人能帮助我吗?

// ProducerManager.h

#include <thread>
#include <queue>

#include "Producer.h"

class ProducerManager {
  public:
    ProducerManager(std::queue<std::string> *buffer, Semaphore *items);
    int run();
  private:
    std::queue<std::string> *buffer;
    Semaphore *items;
    bool empty_page_reached = false;
    unsigned int max_threads = 50;
    unsigned int num_pages = 0;
    std::vector<std::thread> threads;   // If I remove this line, I no longer get the error
    std::vector<Producer*> producers;
    std::queue<int> pids;
};

// ProducerManager.cc

#include "ProducerManager.h"

ProducerManager::ProducerManager(std::queue<std::string> *buffer, Semaphore *items) {
  this->buffer = buffer;
  this->items = items;
}

int ProducerManager::run(void) {
  // Create initial threads
  for (unsigned int i = 0; i < max_threads; i++) {
    producers.push_back(new Producer("http://example.com/stuff.json?page="+std::to_string(i+1), i+1, buffer, items, &pids, &empty_page_reached));
    threads.push_back(std::thread(&Producer::perform, producers[i]));
    num_pages++;
  }

  // Keep respawning threads while we haven't yet found an empty page
  while(!empty_page_reached) {
    if (!pids.empty()) {
      // Replace the thread corresponding to a finished page number
      int idx = pids.front() - 1;
      threads[idx].join();
      delete producers[idx];
      producers[idx] = new Producer("http://example.com/stuff.json?page="+std::to_string(num_pages+1), num_pages+1, buffer, items, &pids, &empty_page_reached);
      threads[idx] = std::thread(&Producer::perform, producers[idx]);
      pids.pop();
      num_pages++;
    }
  }

  // Clean up all remaining threads
  while(!pids.empty()) {
    int idx = pids.front() - 1;
    threads[idx].join();
    delete producers[idx];
    pids.pop();
    num_pages++;
  }

  return num_pages;
}

// Worker.h

#ifndef WORKER_H
#define WORKER_H

#include <iostream>
#include <string>
#include <queue>

#include "Semaphore.h"

class Worker {
  protected:
    std::queue<std::string> *buffer;
    Semaphore *items;
};

#endif

// Producer.h

#include <curl/curl.h>
#include <queue>

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

#include "Worker.h"

class Producer : protected Worker {
  public:
    Producer(std::string link, int page_num, std::queue<std::string> *buffer, Semaphore *items, std::queue<int> *pids, bool *empty_page_reached);

    std::string link;                                                                        
    int perform();
    time_t last_checked;                                                                      
    bool setCurlOptions();

    int getPageNum();                                                                         
    std::string getLink();                                                                     
    void setLastChecked();                                                                    

  private:
    std::string read_buf;                                                                    
    CURL *curl;
    int page_num;                                                                             
    bool *empty_page_reached;
    std::queue<int> *pids;

    int parseJSON();                                                                          

    static size_t writeCallback(char *ptr, size_t size, size_t nmemb, void *userdata);
};

// Producer.cc

#include <time.h>

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

#include "Producer.h"

Producer::Producer(std::string link, int page_num, std::queue<std::string> *buffer, Semaphore *items, std::queue<int> *pids, bool *empty_page_reached) {
  this->link = link;
  this->page_num = page_num;
  this->buffer = buffer;
  this->items = items;
  this->pids = pids;
  this->empty_page_reached;
  setLastChecked();
}

bool Producer::setCurlOptions(void) {
 ...
}

int Producer::perform(void) {
  CURLcode res;

  // Setup curl
  curl = curl_easy_init();

  // Set curl options
  setCurlOptions();

  // Send the request
  res = curl_easy_perform(curl);

  // Cleanup after request
  curl_easy_cleanup(curl);

  if (res == CURLE_OK) {
    parseJSON();
  }

  pids->push(page_num);
  return res;
}

int Producer::getPageNum(void) {
  return page_num;
}

std::string Producer::getLink(void) {
  return link;
}

void Producer::setLastChecked(void) {
  ...
}

size_t Producer::writeCallback(char *ptr, size_t size, size_t nmemb, void *userdata) {
  ...
}

int Producer::parseJSON(void) {
  ...
}

// main.cc

#include <string>
#include <thread>

#include "ProducerManager.h"
#include "Consumer.h"
#include "Semaphore.h"

int main(int argc, char *argv[]) {
  std::queue<std::string> *buffer = new std::queue<std::string>();
  Semaphore *items = new Semaphore(0);

  // Testing with just one consumer
  Consumer *c1 = new Consumer(buffer, items);
  std::thread cth1(&Consumer::perform, c1);

  ProducerManager pm(buffer, items);
  std::thread pm_thread(&ProducerManager::run, pm);

  pm_thread.join();
  cth1.join();

  delete c1;

  return 0;
}

错误:

/usr/include/c++/9.2.1/bits/stl_uninitialized.h: In instantiation of ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::thread*, std::vector<std::thread> >; _ForwardIterator = std::thread*]’:
/usr/include/c++/9.2.1/bits/stl_uninitialized.h:307:37:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::thread*, std::vector<std::thread> >; _ForwardIterator = std::thread*; _Tp = std::thread]’
/usr/include/c++/9.2.1/bits/stl_vector.h:555:31:   required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::thread; _Alloc = std::allocator<std::thread>]’ProducerManager.h:6:7:   required from ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(_UHead&&) [with _UHead = ProducerManager&; long unsigned int _Idx = 1; _Head = ProducerManager]’/usr/include/c++/9.2.1/tuple:349:38:   required from ‘static std::thread::_Invoker<std::tuple<typename std::decay<_Tp>::type, typename std::decay<_Args>::type ...> > std::thread::__make_invoker(_Callable&&, _Args&& ...) [with _Callable = int (ProducerManager::*)(); _Args = {ProducerManager&}; typename std::decay<_Tp>::type = int (ProducerManager::*)()]’/usr/include/c++/9.2.1/thread:131:22:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = int (ProducerManager::*)(); _Args = {ProducerManager&}; <template-parameter-1-3> = void]’main.cc:17:50:   required from here
/usr/include/c++/9.2.1/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range  127 |       static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
c++ multithreading c++11
1个回答
0
投票

制作

std::thread pm_thread(&ProducerManager::run, std::ref(pm));
// or
std::thread pm_thread(&ProducerManager::run, &pm);

std::thread的构造函数按值接受参数。如最初所写,它尝试复制pm,但ProducerManager是不可复制的(因为其成员std::vector<std::thread> threads是不可复制的,因为std::thread是不可复制的。)>

© www.soinside.com 2019 - 2024. All rights reserved.