Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safe way of casting void* to something higher?

I've got a generic class that manages resources of all kinds of types, but since I don't want to create an instance of ResourceManager for every T there is (thus having one resource manager for each type T), I have to make the type of T unknown to the ResourceManager class.

I do this by saving a map of void* pointers and converting them back to the required format if someone requests a certain type out of a templated Load() method;

template <typename T>
T* Load(const std::string &location)
{
    //do some stuff here

    //everybody take cover!!!
    return static_cast<T*>(m_resources[location]);
}

I use template specialization to introduce different Loaders to the class:

template<>
AwesomeType* Load(const std::string &location)
{
    //etc.

    return static_cast<AwesomeType*>(m_resources[location]);
}

I am aware that this is ugly, but there is no way around it right now. I could introduce static maps in the inside of the specialized Load methods, but that way I can't bind the lifetime of the resources to the lifetime of an ResourceManager object, which is an essential feature.

But since this is somewhat dangerous (since those void* pointers can be anything), I'd like to at least check at runtime if the conversion is going to work, so I can react to it without having the application crash.

How can I do this?

like image 364
TravisG Avatar asked Dec 03 '22 01:12

TravisG


1 Answers

There is no way to check what you can cast void* to, unless you store additional information that indicates the actual type with each pointer.

A more "C++ way" to do what you want is to derive each resource class from an abstract base class Resource, and store a map of pointers to Resource in your resource manager. Then you can use dynamic_cast<T*> to convert to the required type, and this will return NULL if the pointer is to an object of the wrong type. Or (depending on what you want to do) you can simply return a Resource* pointer and use virtual functions to implement the functionality of each resource.

like image 140
interjay Avatar answered Dec 26 '22 15:12

interjay