Шаблон мультиварианта.
От: Went  
Дата: 24.02.19 07:31
Оценка:
Доброго дня.
Все еще беспокоит проблема оптимального хранения данных в объекте, которые редко используются. Например, есть некий компонентный объект, у которого огромное множество инкарнаций используют только базовый набор данных, но некоторые используют специальные, причем в произвольных комбинациях. При этом, эти данные разнородные (нельзя завести под общий интерфейс и сложить отдельно) и меняются в процессе исполнения, то есть нельзя сделать шаблон с трейтами.
По мере раздумий пришел к такому мульти-варианту:
void f1()
{
  mystd::multivariant<int, int, string> x; // Пустой объект, в нем ничего нет
  x.get<2>() = "hello"; // Записали строку в 3-ю ячейку.
  ASSERT(!x.has<1>()); // У нас нет 2-го инта.
  x.get<1>() = 1; // 2-ий инт создался и в него записали 1
  ASSERT(x.has<1>()); // У нас есть 2-й инт.
  x.reset<1>(); // Теперь убрали.
}

Таким образом я могу "включать и выключать" любые части мультиварианта. При выключении объект удаляется.
Почему это не сделать набором std::optional, потому что они все едят память, в сумме это может набежать втрое или вдесятеро больше, чем объект в "компактном" виде. Почему не сделать это набором std::unique_ptr — потому что для каждой секции будет свое обращение к куче. А так — все лежит в последовательном буфере. Если объектов мало, они лежат прямо рядом, в статической части, если не помещаются — выделяются на куче. Размер статической части, например, может выбираться как размер наибольшего члена варианта, это уже вопрос оптимизации. Минус такого варианта в том, что операция доступа к тому или иному члену потребует времени, нужно будет посчитать размер предыдущих частей, чтобы найти смещение нужного члена. Ну и всякие "перемещения" при перевыделении памяти.

Вопрос такой: насколько это оправдано или "память давно не ресурс" и ее экономия вылезет большими потерями из-за более сложных алгоритмов доступа? Есть ли где-то такое реализованное?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.