Создатель компонента шаблона фабрики C++ с одноэлементным контейнером

Я реализую фабричный шаблон для создания компонентов и хочу реализовать одноэлементный контейнер для всех экземпляров каждого типа, созданных фабрикой. В идеале это должен быть один вектор для каждого типа, созданного на фабрике.

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

Я думал о том, чтобы сделать что-то вроде этого для фабричной карты:

Map<string,pair<constructorFnPtr, vector<baseClass>>

Это приводит к потере данных из производного класса при его приведении к базовому классу.

Я также думал, что указатель на вектор в качестве второго члена пары будет хорошим способом сделать это, но я не уверен, как это можно реализовать, сохраняя в каждом векторе свой тип данных. Я не думаю, что это было бы возможно, поскольку шаблонные векторы - это технически разные классы.

Есть ли способ сделать то, что я пытаюсь сделать? Последние пару дней я пытался что-то выяснить без удачи.

В качестве альтернативы, если есть другой хороший способ хранения векторов (то есть как статический член класса компонента), я открыт для любых предложений, подобных этому!

2 ответа

Я бы не стал использовать шаблон фабрики для компонентов, а скорее шаблон пула объектов, так как вы, скорее всего, захотите использовать фабрику для управления созданием сущностей.

Я использую базу Component класс для всех компонентов. Это позволяет мне иметь возможность управлять некоторой статической информацией типа времени выполнения для каждого компонента и предоставлять набор общих методов. Затем я реализовал интерфейс IComponentPool это контракт для моего пула объектов компонентов. Затем я определил шаблонный класс ComponentPool<T> что происходит от IComponentPool, Внутри этого шаблонного класса я управляю двумя векторами / массивами. Тогда есть ComponentPoolMap который выставляет некоторое похожее на карту поведение на поиск ComponentPool<T> на основе типов компонентов.

Сейчас в ComponentPool<T> класс, первый массив является разреженным массивом, используемым как поиск. Он содержит смещение индекса относительно того, где компонент находится внутри второго плотно упакованного массива. Разреженный массив может быть просто средством взять EntityId и преобразовать его туда, где находится компонент. Если хотите, вы можете легко внедрить более сложную систему управления верхом этого типа фреймворка.

Идея здесь заключается в том, что упакованный плотный объект выступает в качестве непрерывного буфера памяти, который вы можете легко перебирать в дружественном кэшу поместье в тесных циклах, но разреженный массив обеспечивает одноуровневый поиск косвенного обращения для каждой сущности для компонентов.

Теперь фабричный образец - то, где вы создаете свой Entity или же EntityId обращайтесь к сущности и создайте все необходимые аспекты, которые составляют Орка, Зомби или что-то еще для вашей игры. Фабрика действует как слой, который находится поверх вашей системы игровых объектов, из которой ваш ComponentPoolMap вероятно, только небольшой кусочек этой системы.

Вы не можете сделать это с помощью std::vector смежных объектов.

Причина в том, что фабрика должна строить объекты, а затем возвращать указатель на них. Проблема в том, что указатель будет храниться в вашем приложении во время следующего вызова your_vector.push_back() вероятно, сделает их недействительными, как говорится в документации C++:

Если новый размер () больше емкости (), то все итераторы и ссылки (включая итератор конца-в-конце) становятся недействительными. В противном случае только последний итератор становится недействительным.

Таким образом, ваш следующий вызов на завод может сделать недействительными все ваши предыдущие вызовы.

Другие вопросы по тегам