[英]How can I resolve a circular class dependency when forward declaration is not possible as elegantly as possible?
I have something like this: 我有这样的事情:
struct v_with_holder {
// bunch of fields
holder h; // does not name a type
};
typedef boost::variant</* such types, */v_with_holder/*, many others */> struct_v;
class holder { public: std::vector<struct_v> ss; };
I only added this particular variant recently. 我最近才添加了此特定变体。 All the other ones just have standard, already-defined data types and classes, so they can be copy-constructed, and the code base is written as such (eg with calls to
ss.push_back(v)
). 其他所有代码都具有标准的,已经定义的数据类型和类,因此可以复制构造它们,并且代码库可以这样编写(例如,调用
ss.push_back(v)
)。
The issue is that I can't declare v_with_holder
until I declare holder
, and vice versa. 问题是,直到我声明
holder
,我才能声明v_with_holder
,反之亦然。 A forward declaration class holder;
前瞻性声明
class holder;
gives field 'h' has incomplete type 'holder'
. 给出
field 'h' has incomplete type 'holder'
。
I thought I could use a unique_ptr
: 我以为我可以使用
unique_ptr
:
class holder;
struct v_with_holder {
// bunch of fields
std::unique_ptr<holder> ph;
holder& h;
v_with_holder();
~v_with_holder();
};
typedef boost::variant</* such types, */v_with_holder/*, many others */> struct_v;
class holder { public: std::vector<struct_v> ss; };
v_with_holder::v_with_holder() : ph(new holder), h(*ph) { }
v_with_holder::~v_with_holder() { }
However, the issue now is that v_with_holder
is no longer copy-constructible: 但是,现在的问题是
v_with_holder
不再是可复制构造的:
holder h1, h2;
v_with_holder x;
x.h = h2;
h1.ss.push_back(x); // error: use of deleted function 'v_with_holder::v_with_holder(const v_with_holder&)'
Now it seems that my only recourse is to define copy constructors which just make new unique ptrs and copy the contents. 现在看来,我唯一的求助方法就是定义复制构造函数,这些复制构造函数将创建新的唯一ptrs并复制内容。 And for completeness, move constructors as well.
为了完整起见,也请移动构造函数。 This seems to work ( ideone link ), but it means that I have gotten from my intent, which was this:
这似乎可行( ideone link ),但这意味着我从我的意图中得到了帮助,这是这样的:
struct v_with_holder {
// bunch of fields
holder h;
}
// define struct_v, holder
To this horribleness: 对于这个可怕的事情:
class holder;
struct v_with_holder {
// a bunch of fields
std::unique_ptr<holder> ph;
holder& h;
friend void swap(v_with_holder& first, v_with_holder& second)
{
using std::swap;
// swap a bunch of fields
swap(first.ph, second.ph);
}
v_with_holder();
~v_with_holder();
v_with_holder(const v_with_holder& other);
v_with_holder(v_with_holder&& other);
v_with_holder& operator=(v_with_holder other);
};
// define struct_v, holder
v_with_holder::v_with_holder() : ph(new holder), h(*ph) { }
v_with_holder::~v_with_holder() { }
v_with_holder::v_with_holder(const v_with_holder& other) : ph(new holder), h(*ph)
{
// copy a bunch of fields
h = other.h;
}
v_with_holder::v_with_holder(v_with_holder&& other) : v_with_holder()
{
swap(*this, other);
}
v_with_holder& v_with_holder::operator=(v_with_holder other)
{
swap(*this, other);
return *this;
}
And all to avoid a circular dependency! 一切都是为了避免循环依赖!
Surely, there must be a better way. 当然,必须有更好的方法。 Tell me there is a better way.
告诉我有更好的方法。 Please.
请。 What is this better way?
这是什么更好的方法?
Why not simply do: 为什么不简单地做:
struct v_with_holder {
// bunch of fields
holder *h; //Pointer to holder is of known size
};
typedef boost::variant</* such types, */v_with_holder/*, many others */> struct_v;
class holder { public: std::vector<struct_v> ss; };
Ah okay, it appears I can forward-declare v_with_holder
instead: 好的,看来我可以转发声明
v_with_holder
:
struct v_with_holder;
typedef boost::variant</* such types, */v_with_holder/*, many others */> struct_v;
class holder { public: std::vector<struct_v> ss; };
struct v_with_holder
{
holder h;
};
I did not realize that typedef
s will work with forward-declared types, or that std::vector
can take an undeclared type. 我没有意识到
typedef
可以与前向声明的类型一起使用,或者std::vector
可以采用未声明的类型。 I thought, based on this question and answer , that it couldn't, but this has worked so far on ideone, G++ 4.8.1, and MSVC 2012. 根据这个问题和答案 ,我认为它不可能,但是到目前为止,它已经在ideone,G ++ 4.8.1和MSVC 2012上奏效。
The question still stands if this were somehow not possible. 问题仍然存在,如果这不可能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.