There is an old legacy code which can not be modified. If simplified it looks like this:
enum class Type {A, B, C};
struct Object {Type type;};
Object* objs[N];
int count = 0;
#define addobj(ptr) objs[count++] = (Object*)ptr
struct A {
Type type;
int prop1;
A(int v) : type(Type::A), prop1(v) {addobj(this);}
};
struct B {
Type type;
int prop1;
B(int v) : type(Type::B), prop1(v) {addobj(this);}
};
struct C {
Type type;
int prop1;
C(int v) : type(Type::C), prop1(v) {addobj(this);}
};
A* getA(int id) {return (A*)objs[id];}
B* getB(int id) {return (B*)objs[id];}
C* getC(int id) {return (C*)objs[id];}
In addition, there is "polymorphic" property access, which is allowed to change:
int& prop1ref(int id) {
switch (objs[id]->type) {
case Type::A: return getA(id)->prop1;
case Type::B: return getB(id)->prop1;
}
return getC(id)->prop1;
}
void test() {
A a(1); B b(2); C c(3);
for (int id=0; id<count; id++)
prop1ref(id);
}
Is there a way to replace only property access code in prop1ref with e.g. std::variant and std::visit?
Please note, prop1 name and type do match between classes, but locations (offsets) do not. Type field offset is guaranteed so cast can always be made. Also, new code should allow accessing double prop2, string prop3 etc in A, B, C classes without using macros.