Tra*_*ian 10 c++ stl language-lawyer c++11
我处于这样一种情况,我在两个类的定义之间有一个循环依赖循环,其中(据我所知)两个类都需要另一个类型才能成为完整类型才能正确定义它们.
简而言之,我需要简化版本的内容:
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_;
};
Run Code Online (Sandbox Code Playgroud)
这种情况实际上比上面更复杂,因为Node它实际上将是一个变体类型(类似于boost::variant),它使用placement new来显式构造预分配中的多种类型的对象之一(并且具有正确的对齐,我忽略了在这个简化中)缓冲区:因此缓冲区不是精确的sizeof(Map),而是依赖于某个计算的常量sizeof(Map).
显然,问题是只在前向声明时才sizeof(Map)可用Map.此外,如果我Node首先将声明的顺序更改为forward declare ,那么编译Map失败,因为std::unordered_map<std::string, Node>在Node不完整类型时无法实例化,至少在Ubuntu上使用我的GCC 4.8.2.(我知道这取决于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");
Run Code Online (Sandbox Code Playgroud)
这基本上依赖于std::unordered_map<std::string, T>对于所有T都具有相同大小的假设,这似乎与我使用GCC的测试相符.
我的问题因此有三个:
C++标准中有什么要求这个假设成立吗?(我假设没有,但如果有,我会惊喜......)
如果不是,它是实际上安全的假设它适用于所有合理实现真正反正,和我在修订版的静态断言绝不会火?
最后,还有一个我没想过的更好的解决方法吗?我确信有可能有一些我可以做的事情,而我没有想到,但不幸的是我想不出任何东西......
继续假设吧。然后static_assert在施工时你是对的。
还有更奇特的解决方案,例如弄清楚 boost 递归数据结构如何工作并在此处应用该技术(这可能需要编写您自己的映射),或者仅使用boost::支持不完整数据结构的容器。
| 归档时间: |
|
| 查看次数: |
669 次 |
| 最近记录: |