【发布时间】:2020-12-04 04:43:05
【问题描述】:
以下代码...
// main.cpp
#include <grpcpp/grpcpp.h>
class ClientContextContainer {
public:
ClientContextContainer( int i ) : i_(i) {}
private:
grpc::ClientContext client_context_;
int i_;
};
class ArrayContainer {
public:
ArrayContainer() : ccc_{ {42}, {1138} } {}
private:
ClientContextContainer ccc_[2];
};
int main( int argc, char* argv[] ) {
ArrayContainer ac;
return 0;
}
...产生此错误:
root@178258c7c52d:/tmp# /usr/bin/x86_64-linux-gnu-g++ --version && /usr/bin/x86_64-linux-gnu-g++ -c ./main.cpp
x86_64-linux-gnu-g++ (Debian 8.3.0-6) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
./main.cpp: In constructor 'ArrayContainer::ArrayContainer()':
./main.cpp:15:41: error: use of deleted function 'ClientContextContainer::ClientContextContainer(ClientContextContainer&&)'
ArrayContainer() : ccc_{ {42}, {1138} } {}
^
./main.cpp:4:7: note: 'ClientContextContainer::ClientContextContainer(ClientContextContainer&&)' is implicitly deleted because the default definition would be ill-formed:
class ClientContextContainer {
^~~~~~~~~~~~~~~~~~~~~~
./main.cpp:4:7: error: 'grpc::ClientContext::ClientContext(const grpc::ClientContext&)' is private within this context
In file included from /usr/local/include/grpcpp/client_context.h:37,
from /usr/local/include/grpcpp/grpcpp.h:53,
from ./main.cpp:2:
/usr/local/include/grpcpp/impl/codegen/client_context.h:388:3: note: declared private here
ClientContext(const ClientContext&);
^~~~~~~~~~~~~
我不完全理解编译器错误,但通过我的阅读,它暗示问题在于 class ClientContextContainer 的移动构造函数被隐式删除,因为类的成员 grpc::ClientContext 对象具有私有复制构造函数。 (检查client_context.h 表明它的赋值运算符也是私有的)。
很好。但如果是这种情况,如果我将grpc::ClientContext 成员对象替换为我自己的也具有私有复制构造函数(和赋值运算符)的对象,为什么不能重现编译错误? p>
// main.cpp
//#include <grpcpp/grpcpp.h>
class FauxClientContext {
public:
FauxClientContext() {}
private:
FauxClientContext( const FauxClientContext& );
FauxClientContext& operator=( const FauxClientContext& );
};
class ClientContextContainer {
public:
ClientContextContainer( int i ) : i_(i) {}
private:
FauxClientContext client_context_;
//grpc::ClientContext client_context_;
int i_;
};
class ArrayContainer {
public:
ArrayContainer() : ccc_{ {42}, {1138} } {}
private:
ClientContextContainer ccc_[2];
};
int main( int argc, char* argv[] ) {
ArrayContainer ac;
return 0;
}
root@178258c7c52d:/tmp# /usr/bin/x86_64-linux-gnu-g++ --version && /usr/bin/x86_64-linux-gnu-g++ -c ./main.cpp
x86_64-linux-gnu-g++ (Debian 8.3.0-6) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
root@178258c7c52d:/tmp#
编译main.cpp 的第一个版本的错误的真正性质是什么? 我可以成功编译main.cpp 的第二个版本意味着这不是我将编译器错误消息解释为意思。
对于那些熟悉grpc 的人来说,这个问题的根源是:如果对象有一个成员grpc::ClientContext 对象,是否可以在初始化列表中构造一个对象数组?
【问题讨论】:
-
在过去,在 C++11 之前,阻止复制构造的更好方法之一是创建复制构造函数
private,而不是实现它。看起来grpc::ClientContext被设计为不可复制。 -
现在我想问题是“为什么一个触发复制构造函数而另一个不触发?”不知道。如果我这样做了,我会回答。
-
您可能会发现将
ClientContextContainer(ClientContextContainer&&) = delete;添加到ClientContextContainer的定义中会很有启发性和/或神秘性。也就是说,与其尝试隐式删除移动构造函数,不如显式删除它。 剧透:它仍然可以编译。 -
@JaMit 对于 g++(使用 -std=c++17 -O2 -Wall -pedanti),一旦您向 FauxClientContext 引入一个重要的成员(就像 clientContext 类一样),它就不会编译grpc) 但它至少会与 MSBuild C++17 不一致。
-
这是一个关于 grpc 还是关于移动构造函数的问题?
标签: c++ c++11 grpc copy-constructor move-constructor