【发布时间】:2015-05-13 04:34:04
【问题描述】:
我处于两个类的定义之间存在循环依赖循环的情况,其中(据我所知)两个类都需要另一个类型是完整的类型才能正确定义它们。
简而言之,我需要的简化版是怎么回事:
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),它使用placement new 来显式构造预分配(和正确对齐,我在这个简化中忽略了)缓冲区:因此缓冲区不完全是sizeof(Map),而是一些依赖于sizeof(Map)的计算常数。
问题很明显,当Map 仅被前向声明时,sizeof(Map) 不可用。此外,如果我将声明的顺序更改为首先转发声明Node,那么Map 的编译将失败,因为当Node 是不完整的类型时,std::unordered_map<std::string, Node> 无法实例化,至少对于我的 GCC 4.8.2在 Ubuntu 上。 (我知道它比 GCC 版本更依赖于 libstdc++ 版本,但我不知道如何找到它......)
作为替代方案,我正在考虑以下解决方法:
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 的测试来看,这似乎是正确的。
因此,我的问题有三个:
C++ 标准中有什么要求这个假设成立的吗? (我假设没有,但如果有的话我会很惊喜......)
-
如果不是,实际上是否可以安全地假设它适用于所有合理的实现,并且我的修订版本中的静态断言永远不会触发?
李> 最后,有没有我没想到的更好的解决方法?我敢肯定,有可能我可以做一些我没有想到的显而易见的事情,但不幸的是我什么都想不到......
【问题讨论】:
-
评论不用于扩展讨论;这个对话是moved to chat。
标签: c++ c++11 stl language-lawyer