Eu tenho um registro de componentes que registra componentes (classes/tipos). Eu consegui fazer com que o sistema não funcionasse se você tentasse usá-lo com uma classe que não foi registrada. No entanto, mesmo se ele foi registrado uma vez com um tipo de registro, ele funciona com todos eles porque há um:
template <typename T> static inline component_id;
Isso é colocado dentro da classe pela macro.
template <typename name>
struct ComponentRegistry
{
using this_type = ComponentRegistry;
template <typename component_t>
static char register_new_component(const char* name)
{
static int counter = 0;
component_t::template component_id<this_type> = counter++;
/* REGISTER THE COMPONENT HERE*/
return char(); /* ANYTHING. THE ONLY ONLY REASON THE DUMMY EXISTS IS TO TRIGGER THIS FUNCTION CALL ON PROGRAM INITIALIZATION */
}
template <typename component_t>
int getComponentID()
{
/* IF THE COMPONENT WASN'T REGISTERED WITH ANY REGISTRY AT ALL, THEN THE template component_id DOESN'T EXIST AND SO IT WORKS
- THE PROBLEM IS THAT EVEN IF IT WAS REGISTERED WITH ANOTHER REGISTRY THIS WILL STILL INSTANTIATE THE TEMPLATE
- HOW DO I THROW A COMPILE ERROR? */
return component_t::template component_id<this_type>;
}
};
#define REGISTER_COMPONENT_WITH_REGISTRY(comp_name, ecs_registry_type, comp_type) \
static inline char dummy_assignee_##ecs_registry_type = ecs_registry_type::register_new_component<comp_type>(comp_name); \
template <typename T> \
static inline int component_id;
struct ComponentRegistryName {}; // JUST USED TO DISTINGUISH. EACH TYPE CAN HAVE ITS OWN SET OF COMPONENTS
using ComponentRegistryType = ComponentRegistry<ComponentRegistryName>;
struct MyComponentType
{
REGISTER_COMPONENT_WITH_REGISTRY("MyComponentTypeName", ComponentRegistryType, MyComponentType)
};
struct MyComponentType2
{
/* NOT REGISTERED */
};
int main()
{
ComponentRegistryType component_registry;
component_registry.getComponentID<MyComponentType>(); // THIS SUCCEEDS BECAUSE IT WAS REGISTERED
//component_registry.getComponentID<MyComponentType2>(); // THIS FAILS TO COMPILE BECAUSE THE COMPONENT WASN'T REGISTERED
}
Isso funciona bem para verificar se o componente foi registrado, porque se não foi:
Mas o problema é que se eu quiser registrar o componente em outro tipo de registro, não há mais verificação de restrição porque quando eu faço isso:
componente_t::modelo componente_id
Não existe de forma alguma. No entanto, mesmo se o getComponentID for chamado com um argumento de modelo de um componente que foi registrado em QUALQUER registro, ele terá sucesso. Eu esperava colocar um typedef na classe usando a macro que eu posso verificar como um membro, e se existir, então está bom.
Algo parecido com isso, talvez:
A macro de registro então imprimiria algo como isto:
A macro seria colocada fora da classe do componente, não dentro, como você fez agora.
No registro, você pode acessar o ID do componente como
ComponentIdHolder<this_type, component_t>::component_id
. Isso falharia na compilação para qualquer par de tipos para os quais a especialização não foi fornecida.