【发布时间】:2011-08-01 16:10:44
【问题描述】:
使用以下.thrift文件
struct myElement {
1: required i32 num,
}
struct stuff {
1: optional map<i32,myElement> mymap,
}
我得到了一个带有 STL 映射的节俭生成的类。这个类的实例是长期存在的 (我使用 TSimpleFileTransport 将其追加和删除,以及将其写入磁盘)。
我想在 C++ 中扩展 myElement,扩展不应该影响
此对象的序列化版本(并且此对象未在任何
其他语言)。有什么干净的方法来完成它?
我考虑了以下内容,但它们看起来并不干净:
- 制作第二个使用相同键索引的非节俭映射
- 保持两者同步可能会很痛苦
- 通过对生成的代码进行后处理来修改生成的代码 标头(包括前处理器骇客)。
- 与 #2 类似,但修改生成端以在生成的结构中包含以下内容,然后在强制包含的标头中定义 NAME_CXX_EXT
#ifdef NAME_CXX_EXT NAME_CXX_EXT ... #endif
以上所有看起来都相当讨厌
我现在要采用的解决方案:
[这都是伪代码,没有检查这个副本进行编译]
以下生成的代码,我无法修改 (虽然我可以将地图更改为一组)
class GeneratedElement {
public:
// ...
int32_t num;
// ...
};
class GeneratedMap {
public:
// ...
std::map<int32_t, GeneratedElement> myGeneratedMap;
// ...
};
// End of generated code
应用中的其他地方:
class Element {
public:
GeneratedElement* pGenerated; // <<== ptr into element of another std::map!
time_t lastAccessTime;
};
class MapWrapper {
private:
GeneratedMap theGenerated;
public:
// ...
std::map<int32_t, Element> myMap;
// ...
void doStuffWIthBoth(int32_t key)
{
// instead of
// theGenerated.myGeneratedMap[key].num++; [lookup in map #1]
// time(&myMap[key].lastAccessTime); [lookup in map #2]
Element& el=myMap[key];
el.pGenerated->num++;
time(&el.lastAccessTime);
}
};
我想避免每次访问都进行双重地图查找 (尽管我知道复杂性保持不变,但仍然是两次查找)。
我认为我可以保证对theGenerated 的所有插入和删除)
在一个地方完成,在同一个地方是我填充/删除的地方
myMap 中的相应条目,然后我就可以初始化
Element::pGenerated 到其在Generated.myGeneratedMap 中的对应元素
这不仅可以让我节省一半的查找时间,我什至可以改变 myMap 为我的 keytype 提供更好的容器类型(比如 hash_map 甚至是 boost 多索引图)
起初这对我来说是个坏主意。使用 std::vector 和 std::dqueue 我可以 看看这可能是一个问题,因为值将被移动, 使指针无效。鉴于 std::map 是用树实现的 结构,真的有一个地图元素会被重新定位的时候吗? (我的上述假设在enter link description here的讨论中得到了证实)
虽然我可能不会为 myElement 的每个成员或任何语法糖(如重载 [] () 等)提供访问方法,但这让我可以以几乎一致的方式对待这些元素。唯一的关键是(除了插入)我从不直接寻找mymap 的成员。
【问题讨论】: