I am trying to make a class that registers up to one instance of any single object. More concretely, I want my WidgetRegister class to implement an api like this:
struct WidgetRegister
{
template<class T>
void registerWidget(T *widget);
template<class T>
T *getWidget();
template<class T>
void unregisterWidget();
}
Now, I know that I can't convert T to a string through simple language support, so I plan to make a base Widget subclass like this:
struct Widget
{
static std::string getName() { return "baseWidget"; }
}
There are a few problems I'm facing though:
1) What is the best way to ensure that T can only be a Widget or subclass of WidgetRegister?
I am finding now that if I pass an int or some other object, calling T::getName() will fail as long as it doesn't implement getName(), but will have an arguably non-intuitive error. But even worse, if it does have getName(), the template function will move ahead with whatever getName() returned even though T doesn't inherit from Widget. I guess I could mangle getName() to something longer and more specific to prevent accidents but this doesn't feel "right."
I think the best solution would be some construct in the declaration like
template<class T : public Widget> ...
Is there a language construct like this that I can use?
2) Another nasty: while getWidget() and unregisterWidget() can't deduce T and require <MyWidget> explicitly stated, registerWidget *can* deduce T. If I do:
WidgetExtended *widgetExtended = new WidgetExtended();
Widget *base = widgetExtended;
addGameComponent(base);
registerWidget(T *) will use Widget::getName() instead of WidgetExtended::getName() and thus be WRONG! Can I enforce that the user call the function with <>s?
I can completely sidestep this issue by using virtual functions but now I have to have a T* instantiated to get the name. This will work fine for the register() but not at all for the get and remove.
3) If I continue using the static T::getName() function, is there a way I can enforce subclasses to implement a static T::getName() function also similar in effect to pure virtual functions?
i.e.
class MyWidget : Widget
{
//COMPILE ERROR: because getName() not defined
}
Here the code would not compile if MyWidget was registered with the WidgetRegister but would give a non-intuitive error. Worse, if WidgetRegister and MyWidget never interact, the code WOULD compile.
So, I'm not sure if I should even go this route. I NEED to dynamically instantiate as many widgets as I want, and I NEED to be able to refer to them by string name. I do NOT want typecasting anywhere (I'm going for a completely type safe solution if possible).
I think this almost works, but it seems like too much trouble for what overall is kind of a hack. While the outside interface is fairly simple, elegant, and very type safe, the internals are more complicated than I would like. Even if all the problems above were solved, the code would still be non-trivial to maintain.
Am I trying too hard? Is there a better way?