扩展c++中的thrift生成对象

Extending a thrift generated object in C++

本文关键字:对象 thrift c++ 中的 扩展      更新时间:2023-10-16

使用以下.thrift文件

struct myElement {
  1: required i32 num,
}
struct stuff {
  1: optional map<i32,myElement> mymap,
}

我得到一个带有STL映射的节俭生成的类。该类的实例是长期存在的(我添加并删除它,并使用TSimpleFileTransport将其写入磁盘)。

我想在c++中扩展myElement,扩展应该不会影响此对象的序列化版本(此对象没有在任何其他语言)。有什么干净的方法可以做到这一点?

我考虑了以下内容,但它们似乎并不清晰:

  1. 创建第二个非节俭映射,使用相同的键索引
    • 保持两者同步可能是一种痛苦
  2. 通过对生成的代码进行后处理来修改生成的代码头文件(包括proprocessor hackery).
  3. 与#2类似,但修改生成端,在生成的结构体中包含以下内容,然后在强制包含的头文件中定义NAME_CXX_EXT
      #ifdef NAME_CXX_EXT
      NAME_CXX_EXT ...
      #endif
    

以上这些看起来都很讨厌


我现在要使用的解决方案:

[这都是伪代码,没有检查编译副本]

下面生成的代码,我无法修改(虽然我可以将映射更改为set)

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);
   }
};

我想避免每次访问都使用double map查找(虽然我知道复杂度保持不变,但它仍然是两次查找)。

我想我可以保证所有插入和删除到/从theGenerated)是在一个地方完成的,在同一个地方是我填充/删除在myMap中对应的条目,然后我就可以初始化了元素::pGenerated到生成的mygeneratedmap中对应的元素

这不仅可以让我节省一半的查找时间,我甚至可以改变为我的键类型(例如hash_map或甚至boost)提供更好的容器类型多索引地图)

一开始我觉得这是个坏主意。使用std::vector和std::dqueue,我可以看看这是如何成为一个问题的,因为这些值会被移动,使指针失效。假设std::map是用树来实现的结构,是否真的存在一个映射元素将被重新定位的时间?(我的上述假设在这里输入链接描述的讨论中得到了证实)

虽然我可能不会为myElement的每个成员提供访问方法或任何语法糖(如重载[]()等),但这使我能够以几乎一致的方式处理这些元素。唯一的关键是(除了插入)我从不直接查找mymap的成员。

你考虑过使用简单的集装箱吗?

您正在使用c++,因此您可以将结构体包装在一些类或其他结构体中,并提供包装方法来做任何您想做的事情。