I have an object of class Level that has several subsystems (child objects) it uses to manage its state (e.g. EntityManager, InputManager, Physics). I want to expose some of the methods of those subsystems in the external interface of Level.
Here is one solution:
uint32_t Level::CreateEntity()
{
return entityManager.CreateEntity();
}
Entity& Level::GetEntity(uint32_t entityId)
{
return entityManager.GetEntity(entityId);
}
uint16_t Level::CreateInputState()
{
return inputManager.CreateInputState();
}
void Level::AttachInputState(uint32_t entityId, uint16_t inputStateId)
{
inputManager.AttachInputState(entityId, inputStateId);
}
InputState& Level::GetInputState(uint16_t inputStateId)
{
return inputManager.GetInputState(inputStateId);
}
This solution requires me to duplicate the method declarations inside the Level class and write one-line calls that redirect the control to the subsystem. In projects I have worked on in the past, this has been troublesome to manage.
Another solution is to expose the subsystems in the public interface. Preferably this can be avoided since it’s not important to objects outside of Level which subsystem the calls get forwarded to.
Is there a design that could more elegantly handle this problem?
As requested by the OP I will post a solution that I suggested in the comments.
I am fairly sure, that there is a better one with templates in the new C++ standard but anyway I will post the preprocessor solution which is ugly and should not be used!
This would be used in the class declaration as:
The definition would look like:
And now the very ugly usage to make this work:
I can not guarantee that this will work for any type also I have not tested most of the code. As you can see this “hack” with the input will only work for plain types and not references or pointers. On classes it will trigger the copy constructor!
Of course this can be improved by replacing the VA_ARGS with a variable for the type and the variablename for each argument of the function but again this is very tedious and one would have to write a template for each number of arguments that should be used. This will in result yield nearly as much code as before.
So let me state again: Stick with templates they are by far better than this!
It is just that I do not know how to do it with them. So please if there is anyone out there who knows how to do it with templates, instead of bashing me for this ** code write the beautiful solution everyone here is aching for.