I have a component registry that registers components (classes/types). I've succeeded in making it so that the system doesn't work if you try using it with a class that wasn't registered. However even if it was registered once with one type of registry then it works with all of them because there's a:
template <typename T> static inline component_id;
That is placed inside the class by the 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
}
This works well to check if the component was registered at all because if it wasn't:
But the problem is if I want to register the component to another registry type there's no restriction check anymore because when I do:
component_t::template component_id
Doesn't exist at all. However even if the getComponentID is called on with a template argument of a component that was registered to ANY registry it succeeds. I was hoping to put a typedef in the class using the macro that I can check as a member, and if it exists, then it's good.
Something along these lines, perhaps:
// Declared but not defined.
template <typename Reg, typename Comp>
struct ComponentIdHolder;
The registration macro would then stamp out something like this:
template<>
struct ComponentIdHolder<ecs_registry_type, comp_type> {
static inline int component_id;
};
The macro would be placed outside the component class, not inside as you have now.
Within the registry, you can access the component ID as ComponentIdHolder<this_type, component_t>::component_id
. This would fail to compile for any pair of types for which the specialization wasn't provided.