C++ 错误:隐式删除,因为默认定义格式错误(结构向量)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19883092/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
error: implicitly deleted because the default definition would be ill-formed (vector of structs)
提问by user2057841
I'm having trouble getting my C++ program to compile. Would really appreciate some help with this error. In the header file, I have this:
我在编译 C++ 程序时遇到问题。真的很感激这个错误的一些帮助。在头文件中,我有这个:
struct workerT{
workerT() : status(true), threadSem(0){}
bool status;
std::function<void(void)> func;
semaphore threadSem;
};
std::vector<workerT> workers;
In my .cc file, I am trying to initialize that vector like this:
在我的 .cc 文件中,我试图像这样初始化该向量:
fill(workers.begin(), workers.end(), workerT());
This fails with the error: error: ‘TP::workerT& TP::workerT::operator=(const TP::workerT&)' is implicitly deleted because the default definition would be ill-formed: It points to the semaphore.h file. Semaphore.h is defined like this:
这失败并显示错误:错误:'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;
The program compiles if I remove the "fill" line, but I really need that because I want to initialize the vector. I get the same error message when I make a dummy struct and try to push_back into the vector.
如果我删除“填充”行,程序会编译,但我真的需要它,因为我想初始化向量。当我创建一个虚拟结构并尝试 push_back 到向量中时,我收到相同的错误消息。
Update: thanks @DyP! I still need help compiling. Replaced the "fill" line with this:
更新:谢谢@DyP!我仍然需要帮助编译。用这个替换了“填充”行:
std::generate(workers.begin(), workers.end(), free_func);
Added exactly this to my header:
将这个添加到我的标题中:
workerT free_func(){
return {};
}
Getting these errors:
得到这些错误:
thread-pool.cc: In constructor ‘ThreadPool::ThreadPool(size_t)': thread-pool.cc:33:58: error: argument of type ‘ThreadPool::workerT (ThreadPool::)()' does not match ‘ThreadPool::workerT (ThreadPool::*)()' In file included from /usr/include/c++/4.6/algorithm:63:0, from thread-pool.cc:15: /usr/include/c++/4.6/bits/stl_algo.h: In function ‘void std::generate(_FIter, _FIter, _Generator) [with _FIter = __gnu_cxx::__normal_iterator >, _Generator = ThreadPool::workerT (ThreadPool::*)()]': thread-pool.cc:33:58: instantiated from here /usr/include/c++/4.6/bits/stl_algo.h:5013:2: error: must use ‘.' or ‘->' to call pointer-to-member function in ‘__gen (...)', e.g. ‘(... ->* __gen) (...)' make: *[thread-pool.o] Error 1
线程池.cc:在构造函数“ThreadPool::ThreadPool(size_t)”中:thread-pool.cc:33:58:错误:“ThreadPool::workerT (ThreadPool::)()”类型的参数不匹配“ ThreadPool::workerT (ThreadPool::*)()' 在来自 /usr/include/c++/4.6/algorithm:63:0 的文件中,来自 thread-pool.cc:15: /usr/include/c++/4.6/位/stl_algo.h:在函数'void std::generate(_FIter, _FIter, _Generator) [with _FIter = __gnu_cxx::__normal_iterator >, _Generator = ThreadPool::workerT (ThreadPool::*)()]': thread- pool.cc:33:58: 从这里实例化 /usr/include/c++/4.6/bits/stl_algo.h:5013:2: 错误:必须使用 '. ' 或 '->' 在 '__gen (...)' 中调用指向成员函数的指针,例如 '(... ->* __gen) (...)' make: *[thread-pool.o ] 错误 1
Update-- In my .cc file:
更新——在我的 .cc 文件中:
using namespace std;
static workerT free_func(){
return {};
}
ThreadPool(...args...){
std::generate(workers.begin(), workers.end(), free_func);
}
Errors:
错误:
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
Update again:
再次更新:
static ThreadPool::workerT free_func(){
return {};
}
ThreadPool(...args...){
std::generate(workers.begin(), workers.end(), free_func);
}
In thread-pool.h:
在线程池.h中:
struct workerT{
workerT() : status(true), threadSem(0){}
bool status;
std::function<void(void)> func;
semaphore threadSem;
};
采纳答案by dyp
As 0x499602d2correctly pointed out, fill
needs to copy-assign from the third argument. As your type implicitly is noncopyable, you cannot use fill
.
正如0x499602d2正确指出的那样,fill
需要从第三个参数进行复制分配。由于您的类型隐式不可复制,因此您不能使用fill
.
You could, however, use generate
to fill your vector:
但是,您可以使用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 {};});
}
Note: this only works if noncopyable
has a non-deleted, accessible move constructor. However, if it does nothave such a ctor, you won't be able to use much of the vector (resize
requires MoveInsertable
, which requires either a copy- or move-ctor).
注意:这仅在noncopyable
具有未删除的、可访问的移动构造函数时才有效。但是,如果它没有这样的 ctor,您将无法使用大部分向量(resize
requires MoveInsertable
,它需要复制或移动 ctor)。
For g++4.8, to use generate
, you'll need a free function. I think that's a bug.
对于 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);
}
Yet another question is if you can initializeyour vector like that. I'd say NO. fill
and generate
do not constructelements, but overwrite (assign). That is, you'll already need to have a vector with multiple elements before you can use them.
另一个问题是你是否可以像这样初始化你的向量。我会说不。fill
并且generate
不构造元素,而是覆盖(分配)。也就是说,在使用它们之前,您已经需要有一个包含多个元素的向量。
The easiest version to initializea vector with N default-constructed elements is to use the constructor:
用 N 个默认构造的元素初始化向量的最简单版本是使用构造函数:
std::vector<noncopyable> vec(10);
Creates a vector
with 10 default-constructed elements. The only requirement is that noncopyable
is DefaultConstructible (essentially, it must have a default constructor).
vector
使用 10 个默认构造的元素创建一个。唯一的要求是noncopyable
DefaultConstructible(本质上,它必须有一个默认构造函数)。
If your type is noncopyable AND nonmovable, you cannot use it directly (or as a data member) to store it inside a vector
(*). To make a class C
movable, which contains a noncopyable, nonmovable type X
, you need to store X
as a pointer:
如果您的类型是不可复制且不可移动的,则不能直接使用它(或作为数据成员)将其存储在vector
(*) 中。要使C
包含不可复制、不可移动类型的类可移动,X
您需要将其存储X
为指针:
(*) Well, you can, but you cannot resize the vector, you cannot insert etc.
(*) 好吧,你可以,但你不能调整向量的大小,你不能插入等等。
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;
};
Now you can create a vector<C>
and use it (e.g. resize
, insert
, ...)
现在,您可以创建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);
}