I have a complex node network meant to display graphical information. There are many types of nodes, each derived from a base class Node.
Since the different nodes can present such a wide variety of information, I'd like to add a service lookup for each one. For example, if a node can be drawn, it will implement an IRenderable interface that provides drawing methods. If it has a bounding box, it will implement IBounds; if it can provide vertex information it will extend IVertex and so on. A program examining this graph should then be able to examine each node and query it to see if it provides the indicated service.
In Java this is pretty simple - you just need to use the
instanceof
operator to check if an object implements something. In C++, it seems to be a lot more complicated. I thought of using dynamic_cast, but wasn't sure if that would work if applied to a pointer of the base class. For example, if
BoxNode
extends Node and implements IBounds but Node does not implement IBounds, would 'bounds' be non null in the below code?
1 2
|
Node* n = new BoxNode();
IBounds* bounds = dynamic_cast<IBounds*>(n);
|
Anyhow, I came up with the below solution. It seems to work, but I'm not sure if it's the best way to go about this. I also feel ackward about using void *. Any thoughts on how best to go about this )or maybe if there's something better than a serices lookup) would be appreaciated.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
class ServiceLookup
{
QMap<std::type_index, void*> _serviceMap;
public:
ServiceLookup()
{}
template <typename T>
void registerService(T* service)
{
std::type_index idx = std::type_index(typeid(T));
_serviceMap[idx] = service;
}
template <typename T>
T* lookup() const
{
std::type_index idx = std::type_index(typeid(T));
if (_serviceMap.contains(idx))
return static_cast<T*>(_serviceMap[idx]);
return nullptr;
}
void* lookup(std::type_index idx) const
{
if (_serviceMap.contains(idx))
return _serviceMap[idx];
return nullptr;
}
};
|