Расширение бережливого сгенерированного объекта в C++

Используя следующий .thrift файл

struct myElement {
  1: required i32 num,
}

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

Я получаю бережливый класс с картой STL. Экземпляр этого класса долгоживущий (я добавляю и удаляю из него, а также записываю на диск с помощью TSimpleFileTransport).

Я хотел бы расширить myElement в C++, расширения не должны влиять на сериализованную версию этого объекта (и этот объект не используется ни в одном другом языке). Какой чистый способ добиться этого?

Я рассмотрел следующее, но они не казались чистыми:

  1. Make a second, non thrift map that is indexed with the same key
    • keeping both in sync could prove to be a pain
  2. Модифицируйте сгенерированный код либо путем постобработки сгенерированного заголовка (включая взлом пропроцессора).
  3. Аналогично #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 в соответствующий элемент в theGenerated.myGeneratedMap

Это не только позволит мне сэкономить половину времени поиска, я даже могу изменить myMap на лучший тип контейнера для моего типа ключа (скажем, hash_map или даже карту мультииндекса boost)

Сначала мне это показалось плохой идеей. С std::vector и std::dqueue я вижу, как это может быть проблемой, поскольку значения будут перемещаться, делая указатели недействительными. Учитывая, что std::map реализован с древовидной структурой, действительно ли есть время, когда элемент карты будет перемещен? (мои приведенные выше предположения были подтверждены обсуждением в введите здесь описание ссылки)

Хотя я, вероятно, не буду предоставлять метод доступа к каждому члену myElement или любому синтаксическому сахару (например, перегрузка [] () и т. д.), это позволяет мне обрабатывать эти элементы почти согласованным образом. Единственный ключ в том, что (помимо вставки) я никогда не ищу членов mymap напрямую.


person nhed    schedule 01.08.2011    source источник


Ответы (1)


Рассматривали ли вы просто использование простого контейнеровоза?

Вы используете C++, поэтому вы можете просто обернуть структуру (структуры) в какой-либо класс или другую структуру и предоставить методы-оболочки, чтобы делать все, что вы хотите.

person pickypg    schedule 01.08.2011
comment
если я вас правильно понял, вы предлагаете мне обернуть stuff в другой класс. Если да, то как это поможет мне расширить myElements? Если это не то, что вы имели в виду, то, думаю, мне нужен пример. В конце концов, кажется, что нужно разработать множество методов доступа, основным преимуществом которых является синтаксис (сахар) для внешнего пользователя. - person nhed; 02.08.2011