Есть необходимость в создании контейнера, который может в себе хранить разнотипные данные (но с общим интерфейсом), но с уникальными ID. Так же, этот контейнер должен уметь хранить в себе такие же контейнеры, как он сам.
На первый взгляд сразу приходит в голову следующая конструкция
std::map<long, boost::any>
Однако, RTTI в проекте не включен и в идеале, включать его не хотелось бы.
Что требуется от контейнера:
1. добавить элемент
2. найти и вернуть именно тот тип элемента, который был добавлен, если элемента нет или тип не соответствует то эксепшн.
3. Иметь функцию, которая ищет элемент заданного типа по ID, сначала внутри себя, а потом, если не нашел, внутри всех элементов, которые являются контейнерами
4. Удалять элемент по id
Итак, контейнер хранит внутри себя как одиночные типы, так и контейнеры одиночных типов, контейнеры, могут содержать внутри себя другие контейнеры и т.д.. Все одиночные типы имеют общий базовый класс, все контейнеры тоже имеют общий (но не как у одиночных элементов) базовый класс
Приведу пример:
class ISimpleElement
{
//...
};
class SimpleElementA : public ISimpleElement
{
//...
};
class SimpleElementB : public ISimpleElement
{
//...
};
class IContainer
{
//...
};
class Container1 : public IContainer
{
// ...
};
class Container2 : public IContainer
{
// ...
};
int main()
{
Container1 cont1;
Container2 cont2;
cont1.add(0, new SimpleElementA);
cont1.add(1, new SimpleElementB);
SimpleElementA* A = cont1.get<SimpleElementA>(0); // возвращает указатель на элемент нужного типа
SimpleElementA* A1 = cont1.get<SimpleElementA>(1); // кидает эксепшн, что типа не соответствует типу хранимого элемента
SimpleElementA* A2 = cont1.get<SimpleElementA>(3); // кидает эксепшн, элемента с таким id нет в контейнере
cont2.add(2, new SimpleElementA);
cont2.add(3, new SimpleElementB);
cont2.add(4, &cont1); // еще не определился что будут передаваться указатели, скорее всего будут смарт поинтеры, но сейчас это не важно - просто пример
SimpleElementA* A3 = cont2.get<SimpleElementA>(0); // ищет сначала внутри себя, а потом в других контейнерах внутри себя, когда находит - возвращает, не находит - кидает эксепшн
Container1* p_cont1 = cont2.get<Container1>(4); // возвращает контейнер
}
Понятно, что нужно запретить добавлять контейнеры друг в друга и добавлять контейнеры, которые уже есть в иерархии, но это уже другой вопрос, сейчас надо хотя бы понять как можно решить такую задачу и в каком направлении двигаться.
Всего разных типов простых элементов и контейнеров около 10 каждого. Это число будет расти, но сильно не вырастет. Поэтому хотелось бы решение, при котором не надо писать много кода при добавлении нового типа элемента.