Ошибка: неявно удалена, поскольку определение по умолчанию будет плохо сформировано (вектор структур)

У меня возникла проблема с компиляцией моей программы на С++. Было бы очень полезно помочь с этой ошибкой. В файле заголовка у меня есть следующее:

struct workerT{
 workerT() : status(true), threadSem(0){}
 bool status;
 std::function<void(void)> func;
 semaphore threadSem;
};

std::vector<workerT> workers;

В моем .cc файле я пытаюсь инициализировать этот вектор следующим образом:

fill(workers.begin(), workers.end(), workerT());

Это не выполняется с ошибкой: ошибка: "TP:: workerT & TP:: workerT:: operator = (const TP:: workerT &) неявно удаляется, поскольку определение по умолчанию будет плохо сформировано: Он указывает на файл semaphore.h. Semaphore.h определяется следующим образом:

 public:
  semaphore(int value = 0);
  ....

private:
  int value;
  ....
  semaphore(const semaphore& orig) = delete;
  const semaphore& operator=(const semaphore& rhs) const = delete;

Программа компилируется, если я удаляю строку "fill", но мне это действительно нужно, потому что я хочу инициализировать вектор. Я получаю то же сообщение об ошибке, когда создаю фиктивную структуру и пытаюсь нажать _back в вектор.

Обновление: спасибо @DyP! Мне все еще нужна помощь в компиляции. Замените строку "fill" следующим образом:

std::generate(workers.begin(), workers.end(), free_func);

Добавлено именно это в мой заголовок:

workerT free_func(){
 return {};
}

Получение этих ошибок:

thread-pool.cc: В конструкторе ThreadPool:: ThreadPool (size_t): thread_pool.cc:33:58: error: аргумент типа 'ThreadPool:: workerT (ThreadPool::)() не соответствует' ThreadPool:: workerT (ThreadPool:: *)() В файле, включенном в /usr/include/c ++/4.6/algorithm:63:0,                from thread-pool.cc:15: /usr/include/c ++/4.6/bits/stl_algo.h: В функции 'void std:: generate (_FIter, _FIter, _Generator) [с _FIter = __gnu_cxx:: __ normal_iterator > , _Generator = ThreadPool:: workerT (ThreadPool:: *)()]: thread -pool.cc33:58: экземпляр отсюда /usr/include/c ++/4.6/bits/stl_algo.h:5013:2: error: должен использовать '. или '- > для вызова функции указатель-член в' __gen (...), например. '(... → * __gen) (...) make: * [thread-pool.o] Ошибка 1

Обновление - в моем файле .cc:

 using namespace std;

 static workerT free_func(){
   return {};
 }

 ThreadPool(...args...){
   std::generate(workers.begin(), workers.end(), free_func);
 }

Ошибки:

thread-pool.cc:19:10: error: ‘workerT’ does not name a type
thread-pool.cc: In constructor ‘ThreadPool::ThreadPool(size_t)’:
thread-pool.cc:39:49: error: ‘free_func’ was not declared in this scope
make: *** [thread-pool.o] Error 1

Обновить снова:

 static ThreadPool::workerT free_func(){
    return {};
 }

 ThreadPool(...args...){
   std::generate(workers.begin(), workers.end(), free_func);
 }

В thread-pool.h:

 struct workerT{
 workerT() : status(true), threadSem(0){}
 bool status;
 std::function<void(void)> func;
 semaphore threadSem;
};

Ответ 1

Как 0x499602d2 правильно указано, fill необходимо скопировать назначение из третьего аргумента. Поскольку ваш тип неявно является неготовным, вы не можете использовать fill.

Вы могли бы использовать generate для заполнения вашего вектора:

#include <vector>
#include <algorithm>

struct noncopyable
{
    noncopyable() = default;

    // make it noncopyable
    noncopyable(noncopyable const&) = delete;
    noncopyable& operator=(noncopyable const&) = delete;

    // make it movable (thanks, gx_)
    noncopyable(noncopyable&&) = default;
    noncopyable& operator=(noncopyable&&) = default;
};

int main()
{
    std::vector<noncopyable> vec(10);
    std::generate(begin(vec), end(vec), []()->noncopyable{return {};});
}

Примечание: это работает только в том случае, если noncopyable имеет не удаленный доступный конструктор перемещения. Однако, если у него нет такого ctor, вы не сможете использовать большую часть вектора (resize требует MoveInsertable, для которого требуется либо копирование, либо move-ctor).


Для g++ 4.8, чтобы использовать generate, вам понадобится бесплатная функция. Я думаю, что ошибка.

#include <vector>
#include <algorithm>

struct noncopyable
{
    noncopyable() = default;
    noncopyable(noncopyable const&) = delete;
};

noncopyable free_func()
{  return {};  }

int main()
{
    std::vector<noncopyable> vec;
    std::generate(begin(vec), end(vec), free_func);
}

Еще один вопрос: если вы можете инициализировать свой вектор таким образом. Я бы сказал НЕТ. fill и generate не создают элементы, а переписывают (присваивают). То есть вам уже понадобится вектор с несколькими элементами, прежде чем вы сможете их использовать.

Простейшая версия для инициализации вектора с N построенными по умолчанию элементами заключается в использовании конструктора:

std::vector<noncopyable> vec(10);

Создает vector с 10 созданными по умолчанию элементами. Единственное требование - noncopyable - DefaultConstructible (по существу, он должен иметь конструктор по умолчанию).


Если ваш тип не подлежит копированию и недоступен, вы не можете использовать его напрямую (или как элемент данных) для хранения его внутри vector (*). Чтобы сделать класс C movable, который содержит не подлежащий копированию, неподвижный тип X, вам нужно сохранить X в качестве указателя:

(*) Ну, вы можете, но вы не можете изменять размер вектора, вы не можете вставлять и т.д.

struct nocopies_nomoves
{
    nocopies_nomoves() = default;

    nocopies_nomoves(nocopies_nomoves const&) = delete;
    nocopies_nomoves& operator=(nocopies_nomoves const&) = delete;

    // not required to be explicitly deleted:
    nocopies_nomoves(nocopies_nomoves&&) = delete;
    nocopies_nomoves& operator=(nocopies_nomoves&&) = delete;
};

#include <utility>
#include <memory>
class C
{
public:
    C() : ptr( new nocopies_nomoves() ) {} // make_unique in C++1y

    // I don't think you need to explicitly define those as defaulted;
    // at least not if you don't declare ANY of the copy/move ctors, assignment ops
    // and dtor
    C(C&& rhs) = default;
    C& operator=(C&& rhs) = default;
    ~C() = default;

    // not required to be explicitly deleted:
    C(C const&) = delete;
    C& operator=(C const&) = delete;
private:
    std::unique_ptr<nocopies_nomoves> ptr;
};

Теперь вы можете создать vector<C> и использовать его (например, resize, insert,...)

#include <vector>
#include <algorithm>

static C generate_C()
{
    return {};
}

int main()
{
    std::vector<C> vec(10);
    // note: futile statement below; overwrites the 10 default-constructed
    //       elements
    std::generate(begin(vec), end(vec), generate_C);
}