1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
# Enum serialization runtime support library
{% note warning %}
This library should not be used or referred directly.
Use `GENERATE_ENUM_SERIALIZATION_WITH_HEADER` and `GENERATE_ENUM_SERIALIZATION` macros instead.
{% endnote %}
## Implementation details
### Code bloat
Использование шаблонов вида `TVector<EEnum>`, `std::array<EEnum>` или `TMap<EEnum, TStringBuf>`, а также алгоритмов поверх них, приводит к значительному разбуханию коде. Так как компилятор для разных перечислений вынужден генерировать разные специализации, даже если они компилируются в идентичный машинный код.
Можно во многом выиграть если хранить не массив из `EEnum`, а массив из `std::underlying_type_t<EEnum>` (или из `TSelectEnumRepresentationType<EEnum>::TType`).
Ведь различных типов-перечислений намного больше, чем целочисленных типов, на которых они базируются (и тем более больше, чем различных `TSelectEnumRepresentationType::TType`, коих всего четыре).
И когда компилятор встречает вызов `std::lower_bound`, то для двух массивов из двух перечислений `enum A: int {}` и `enum B: int{}` он создаст две специализации, а если использовать целочисленные типы — то только одну.
Всё это позволяет вынести вызовы вроде `std::lower_bound` в универсальные и переиспользуемые функции, принимающие например `(TArrayRef<const int> values, int enumValue)` своими аргументами.
За счёт этого код
1) быстрее компилируется,
2) результат получается более компактным,
3) как следствие, он меньше засоряет во время исполнения кеш инструкций процессора одинаковыми или очень похожими специализациями функций.
Преобразование между `enum` и `int` выносится в пользовательский код (в шаблонные `inline` функции), и производится только в момент непосредственного использования (первым действием в семействе функций `ToString`, последним действием в семуйстве функций `FromString`), где оптимизирующий компилятор обычно может заменить их на no-op или на простые операции со значениями в регистрах.
А контейнеры вида `TVector<EEnum>` и `TMap<EEnum, ...>`, которые возвращаются из функций `util/generic/serialized_enum.h`, заменяются на специальные классы `TArrayView` и `TMappedDictView`. Они также поддерживают быстрое и преобразование из перечислений в целочисленные типы и обратно в момент использования, и не требуют создавать специализации для каждого из возможных типов-перечислений.
|