Yesterday I came up with a new way to make type conversions prettier.
I want to explain you how that works in this post.
As you might know, I work with a component based object model in my engine (
see here).
In this kind of object model, you sometimes need to modify the component of certain objects after you added them.
To do that I implement a getComponent() function, which - in the past - returned a object of the type of the component interface (called IComponent). Type conversions needed to be made afterwards to work with the desired implementation. That used to look like this:
GameObject gameobject;
RenderableComponent *renderableComponent = new RenderableComponent("graphic.png");
gameobject.addComponent(renderableComponent);
//Somewhere else in the code in another function.
IComponent *component = gameobject.getComponent("RenderableComponent");
RenderableComponent *renderableComponent = static_cast<RenderableComponent*>(component);
//.. do stuff with renderablecomponent.
I found that code pretty ugly and unnecessary complicated, so I thought of another idea to do that user friendlier. The first step I did was to change the getComponent() function to a template function.
The function looked like this:
IComponent *GameObject::getComponent(const String &componentName){
for(std::list<IComponent*>::iterator i = this->m_components.begin();i != this->m_components.end();i++){
if((*i)->getType() == componentName){
return (*i);
}
}
return NULL;
}
With template support it now looks like this:
template<class T>
T *getComponent(const String &componentName){
for(std::list<IComponent*>::iterator i = m_components.begin();i != m_components.end();i++){
if((*i)->getType() == componentName){
return static_cast<T*>((*i));
}
}
return NULL;
}
(Hint: If you don't know nothing about template functions, check
here)
As you can see, the user determines the return type via the template type ( So there's no ugly conversion needed afterwards.)
The result is (in my opinion) much nicer source code.
The following is the above example reused with the new getComponent() template function:
GameObject gameobject;
RenderableComponent *renderableComponent = new RenderableComponent("graphic.png");
gameobject.addComponent(renderableComponent);
//Somewhere else in the code in another function.
//IComponent *component = gameobject.getComponent("RenderableComponent");
//RenderableComponent *renderableComponent = static_cast<RenderableComponent*>(component);
RenderableComponent *renderableComponent = gameobject.getComponent<RenderableComponent>("RenderableComponent");
//.. do stuff with renderablecomponent.
I don't know what about you, but I find it much nicer ;) .
Compared with a macro like:
#define GET_COMPONENT(type)(getComponent<type>(#type))
The example could even get more improved to look like this:
GameObject gameobject;
RenderableComponent *renderableComponent = new RenderableComponent("graphic.png");
gameobject.addComponent(renderableComponent);
//Somewhere else in the code in another function.
//IComponent *component = gameobject.getComponent("RenderableComponent");
//RenderableComponent *renderableComponent = static_cast<RenderableComponent*>(component);
RenderableComponent *renderableComponent = gameobject.GET_COMPONENT(RenderableComponent);
//.. do stuff with renderablecomponent.