Я довольно новичок в шаблонах и функциях времени компиляции, и в настоящее время я пытаюсь написать базовую сущность-компонент-систему (ECS), которая позволит мне хранить универсальные типы (компоненты) в контейнерах. Я хочу, чтобы функциональность могла настраивать мои контейнеры во время компиляции и во время выполнения. В моем приложении есть несколько случаев, когда я точно знаю, какие компоненты всегда будут существовать для сущности, поэтому я хочу иметь возможность их настроить и зарезервировать слоты во время компиляции. Тогда бывают случаи, когда компоненты нужно будет удалять / добавлять динамически во время выполнения.
template <typename T, size_t N>
struct ComponentArray {
public:
template<typename... Args>
constexpr const T& AddComponent(const uint64_t entity, Args &&... args) const
{
//T component{ std::forward<Args>(args)... }; //i want to be able to do something like this..
//m_components[0] = component; //create the component and give it a slot, but this is const
return m_components[0];
}
std::array<T, N> m_components = {};
std::array<T, N> m_entityIds = {};
uint32_t m_used = 0;
};
template <uint64_t entityId, typename Component, typename ... Args>
constexpr const Component& AddComponentCT(Args&&... args)
{
constexpr uint64_t componentHash = GetHashForString(ComponentTypeInfo<Component>::m_name, ComponentTypeInfo<Component>::m_nameLength);
constexpr uint64_t storageHash = ComponentStorageMapping<componentHash>::m_hash;
static_assert(storageHash == componentHash);
constexpr const auto& componentStorage = ComponentStorageMapping<componentHash>::m_componentStorage;
constexpr const Component& rComponent = componentStorage.AddComponent(entityId /*std::forward<Args>(args)...*/);
return rComponent;
}
constexpr const TransformComponent transform = AddComponentCT<ENTITY_ID, TransformComponent>(5.0f, 5.0f, 5.0f);
Это работает, и когда я нахожу указатель мыши над transform
, я вижу, что возвращается, но, очевидно, неверные значенияпоскольку я не могу построить тип, используя аргументы в функции const.
Я также пытался удалить некоторые константы из переменных, но потом жалуется, что вещи не константны или не могут быть оценены.
Я пытаюсь создать тип Component
с предоставленными аргументами, а затем найти свободный слот в m_components
для его хранения. Возможно ли что-то подобное во время компиляции? Если у кого-то есть предложения о том, как я могу достичь того, чего хочу, или улучшить решение, это будет очень цениться. Здесь есть некоторый макрос, который я не включил, который генерирует классы, такие как ComponentStorageMapping
, ComponentTypeInfo
и m_componentStorage
Ниже приведена более упрощенная / универсальная версия, запрошенная в комментариях.
struct A
{
float x, y, z;
};
struct B
{
int i, j, k;
};
template <typename T, size_t N>
struct C {
public:
template<typename... Args>
constexpr const T& AddToArray(Args &&... args) const
{
//T element{ std::forward<Args>(args)... }; //i want to be able to do something like this..
//m_array[0] = element; //create the component and give it a slot, but this is const
return m_array[0];
}
std::array<T, N> m_array = {};
};
template <typename T, typename ... Args>
constexpr const T& AddElement(Args&&... args)
{
constexpr const T& element = C<T, 50>::AddToArray(/*std::forward<Args>(args)...*/);
return element;
}
constexpr const A& someArrayElement = AddElement<A>(5.0f, 5.0f, 5.0f); //this would point to C<A,50>::m_array[0], fully constructed
constexpr const A& someArrayElement2 = AddElement<A>(10.0f, 10.0f, 10.0f); //this would point to C<A,50>::m_array[1], fully constructed
constexpr const B& someArrayElement3 = AddElement<B>(1, 1, 1); //this would point to C<B,50>::m_array[0], fully constructed
constexpr const B& someArrayElement4 = AddElement<B>(2, 2, 2); //this would point to C<B,50>::m_array[1], fully constructed
Для записи я создал еще один пост (https://gamedev.stackexchange.com/questions/176301/how-can-i-create-a-templated-function-to-add-components-to-their-necessary-conta) до этого, чтобы посмотреть, как я буду подходить к этой ситуации, и не получил много предложений, поэтому я просто попытался сделать это сами это - проблема, с которой я столкнулся. Есть другая структура, достигающая того, что я пытаюсь сделать в некотором роде, но я не совсем понимаю, что они делают, поскольку это все шаблоны. Ссылки на структуру находятся в другойпочта.