I'm using type erasure (void cast) to store multiple basic types (float, bool, int etc.) in a one-to-one map. One way to reinterpret the original data type is to use a pair/union/class instead to store the value with a type identifier (e.g. pair). Is there a clean way to resolve the basic type without an identifier using C++11 without Boost?
std::map<int, void *> m_mymap;
// avoid std::map<int, pair<void, MyEnum> > m_mymap;
template <class T> void setValue<T>(int i_key, T i_val)
{
m_mymap[i_key] = reinterprete_cast<void *>(i_val);
}
template <class T> T getValue<T>(int i_key)
{
return reinterprete_cast<T>(i_val);
}
doSomeWork()
{
for (const auto & elem : m_mymap)
{
auto val = some_magical_cast< ??? >(elem.second) // resolve type without a nasty switch against MyEnum
// do some work
}
}
Edit: Update question to use void *
auto val = some_magical_cast< ??? >(elem.second) // resolve type without a nasty switch against MyEnum
C++ is a statically typed language. Every type must be known at compile time. What you're trying to do would require that the type be determined at runtime, based on what was put into the map.
That's not possible with anything in C++. val
must have a single, specific type, not a type determined by executing runtime code. And every iteration of the loop must give it the same type. A union or variant
would allow you to store one of several types, determined at runtime. But the set of types they store is fixed at compile time.
Even if auto val
could somehow result in a series of different types, a void*
does not contain any information which could be used to recover the type it pointed to. Notice that boost/std::any
also lacks any ability to recover this type; you have to ask for a specific type (the difference being that if you ask for the wrong type, any
will fail, while void*
will give you UB).
So no, this is not possible.