Erik said:
How? I'm not saying that it's impossible but I don't know how, and if
it's possible I'd like to know how. My problem is that I can't figure
out how to store the name/type register, all data-structures I know of
can only store instances of objects not a type itself.
You don't need to store the "type" itself (that's abstract information
available at compile time and I already said that when you query/get the
object you will have to presume/know the type to get it) but store some
RTTI (typeid().name) string to help you at runtime at least throw if you
are trying to read it back as another type (so it's runtime type safe).
Example:
template<typename T>
void
registerObject(T& obj, std::string const& name) {
someMap.insert(std::make_pair(name, Object(obj)));
}
template<typename T>
T&
get(std::string const& name) {
SomeMap::const_iterator cit(someMap.find(name));
if (name == someMap.end())
throw // type not found
return cit->get<T>();
}
class Object
{
template<typename T>
explicit Object(T& obj)
: m_ptr(&obj), m_rtti(typeid(T).name) {}
template<typename T>
T& get() const {
if (m_rtti != typeid(T).name)
throw std::bad_cast;
return *static_cast<T*>(m_ptr);
}
private:
void* m_ptr;
std::string const m_rtti;
};
I have not tried to compile the code but I know it the principle behind it
works because I used something similar for some serialization code. Also
note that when using get the called must presume the type as in:
SomeType& obj(get<SomeType>("SomeType"));
But at least if the type presumed is wrong you get an exception. Obviously
this cannot be solved at compile time if you decide at runtime what
types/objects to register and for what names.