I would like to iterate some code over a few maps that have different value types, but which are all derived from a base class, which I can guarantee is the first inherited class, and the classes are plain old data.
I could probably use templated functions, or use maps of pointers, but I would rather not.
This seems to work in the tests I perform. Is it valid code?
#include <iostream>
#include <map>
using std::map;
struct Base
{
double a;
};
struct Derived : Base
{
};
map<int, Derived> mapOfDerived;
map<int, Base> mapOfBase;
int main()
{
mapOfDerived[2].a = 4;
mapOfDerived[4].a = 5;
mapOfBase [1].a = 7;
mapOfBase [5].a = 1;
for (auto& map_ptr :
{ (map<int, Base>*) &mapOfDerived,
(map<int, Base>*) &mapOfBase
})
for (auto& [key, val] : *map_ptr)
{
std::cout << std::endl << key << " " << val.a;
}
return 0;
}
No, that's undefined behavior.
You cannot cast a pointer to one class type to a pointer of another and use the result as if it was really pointing to an object of the target type, except if the classes are related by inheritance, which map<int, Derived>
and map<int, Base>
are not, or in a few very specific other situations, e.g. members of unions, which also don't apply.
Don't use C-style casts. They make the compiler do almost any type cast, regardless of whether the result is actually allowed to be used. Had you used a C++-style static_cast
instead, the compiler would have correctly complained to you.