Используя следующий .thrift
файл
struct myElement {
1: required i32 num,
}
struct stuff {
1: optional map<i32,myElement> mymap,
}
Я получаю сгенерированный комиссионный класс с картой STL. Экземпляр этого класса долгоживущий
(Я добавляю и удаляю его, а также записываю на диск с помощью TSimpleFileTransport).
Я хотел бы расширить myElement
в C ++, расширения не должны влиять
сериализованная версия этого объекта (и этот объект не используется ни в
другой язык). Какой простой способ добиться этого?
Я размышлял о следующем, но они не казались чистыми:
- Создайте вторую нетривиальную карту, индексированную с тем же ключом
- синхронизация обоих данных может оказаться болезненной
- Изменить сгенерированный код либо путем последующей обработки сгенерированного
заголовок (включая взлом пропроцессора).
- Аналогично # 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 для лучшего типа контейнера для моего типа ключа (скажем, hash_map или даже повышение
многоиндексная карта)
Сначала это звучало для меня как плохая идея. С помощью std :: vector и std :: dqueue я могу
посмотрим, как это может быть проблемой, так как значения будут перемещаться,
аннулирование указателей. Учитывая, что std :: map реализован с помощью дерева
структура, есть ли время, когда элемент карты будет перемещен?
(мои предположения были подтверждены обсуждением в введите описание ссылки здесь )
Хотя я, вероятно, не буду предоставлять метод доступа каждому члену myElement
или любому синтаксическому сахару (например, перегрузке [] () и т. Д.), Это позволяет мне обрабатывать эти элементы почти согласованным образом. Единственный ключ в том, что (кроме вставки) я никогда не ищу членов mymap
напрямую.