我处于两个类的定义之间存在循环依赖关系循环的情况下,(据我所知)两个类都需要另一个类型为完整类型才能正确定义它们。
用简化的术语来说,我需要的是正在发生的事情的简化版本:
struct Map;
struct Node {
// some interface...
private:
// this cannot be done because Map is an incomplete type
char buffer[sizeof(Map)];
// plus other stuff...
void* dummy;
};
struct Map {
// some interface...
private:
// this is Map's only member
std::unordered_map<std::string, Node> map_;
};
这种情况实际上比上述情况更为复杂,因为
Node
实际上将是一种变体类型(类似于boost::variant
),它使用new放置来显式构造预分配的多种对象之一(并具有正确的对齐方式,我将我忽略了这种简化)缓冲区:因此,该缓冲区并非完全是sizeof(Map)
,而是一些依赖于sizeof(Map)
的计算常数。显然,问题在于仅向前声明
sizeof(Map)
时Map
不可用。此外,如果我更改声明的顺序以先转发声明Node
,则Map
的编译将失败,因为当std::unordered_map<std::string, Node>
是不完整的类型时,至少在我的GCC 4.8.2上,无法实例化Node
。 (我知道它对libstdc++版本的依赖比对GCC版本的依赖更大,但我不容易知道如何找到它……)作为替代方案,我正在考虑以下解决方法:
struct Node {
// some interface...
private:
// doing this instead of depending on sizeof(Map)
char buffer[sizeof(std::unordered_map<std::string, void*>)];
// other stuff...
void* dummy;
};
struct Map {
// some interface...
private:
// this is Map's only member
std::unordered_map<std::string, Node> map_;
};
// and asserting this after the fact to make sure buffer is large enough
static_assert (sizeof(Map) <= sizeof(std::unordered_map<std::string, void*>),
"Map is unexpectedly too large");
这基本上是基于
std::unordered_map<std::string, T>
对于所有T都是相同的大小的假设,这在我使用GCC进行的测试中似乎成立。因此,我的问题是三方面的:
最佳答案
只是继续假设。然后在构建正确的static_assert
时是正确的。
有一些更高级的解决方案,例如弄清楚boost递归数据结构是如何工作的,并在此处应用该技术(可能需要编写自己的 map ),或者仅使用支持不完整数据结构的boost::
容器。
关于c++ - 假定所有的T的sizeof(std::unordered_map <std::string,T>)都是相同的,实际上是安全的吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30205748/