错误:隐式删除,因为默认定义将是格式错误(结构的向量)

时间:2013-11-09 21:03:25

标签: c++

我无法编译C ++程序。真的很感激这个错误的一些帮助。在头文件中,我有这个:

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&amp;隐式删除TP :: workerT :: operator =(const TP :: workerT&amp;)',因为默认定义不正确: 它指向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;

如果我删除“填充”行,程序会编译,但我真的需要它,因为我想初始化向量。当我创建一个虚拟结构并尝试将push_back放入向量时,我得到相同的错误消息。

更新:谢谢@DyP!我仍然需要帮助编译。用这个替换了“填充”行:

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中包含的文件中,                  来自thread-pool.cc:15: /usr/include/c++/4.6/bits/stl_algo.h:在函数'void std :: generate(_FIter,_FIter,_Generator)[with _FIter = __gnu_cxx :: __ normal_iterator&gt;,_Generator = ThreadPool :: workerT(ThreadPool: :*)()]': thread-pool.cc:33:58:从这里实例化 /usr/include/c++/4.6/bits/stl_algo.h:5013:2:错误:必须使用'。'或' - &gt; '来调用'__gen中的指针到成员函数(...)',例如'(... - &gt; * __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 个答案:

答案 0 :(得分:6)

正如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,这需要复制或移动-构造函数)。


对于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);
}

另一个问题是,你是否可以像这样初始化你的矢量。我会说不。 fillgenerate构造元素,但覆盖(assign)。也就是说,在使用它们之前,你需要有一个包含多个元素的向量。

使用N个默认构造元素初始化向量的最简单版本是使用构造函数:

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

使用10个默认构造元素创建vector。唯一的要求是noncopyable是DefaultConstructible(实质上,它必须有一个默认的构造函数)。


如果您的类型是不可复制的且不可移动的,则不能直接使用它(或作为数据成员)将其存储在vector(*)中。要使类C可移动,其中包含不可复制的,不可移动的类型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>并使用它(例如resizeinsert,...)

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