There is an old legacy code which can not be modified. If simplified it looks like c++ calculator program:
Code:
[COLOR=var(--highlight-keyword)]enum class[/COLOR][COLOR=var(--highlight-color)][/COLOR][COLOR=var(--highlight-literal)]Type[/COLOR][COLOR=var(--highlight-color)] {A, B, C};[/COLOR][COLOR=var(--highlight-keyword)]struct[/COLOR] [COLOR=var(--highlight-literal)]Object[/COLOR] {Type type;};
Object* objs[N];
[COLOR=var(--highlight-namespace)]int[/COLOR] count = [COLOR=var(--highlight-namespace)]0[/COLOR];
[COLOR=var(--highlight-keyword)]#[COLOR=var(--highlight-keyword)]define[/COLOR] addobj(ptr) objs[count++] = (Object*)ptr[/COLOR]
[COLOR=var(--highlight-keyword)]struct[/COLOR] [COLOR=var(--highlight-literal)]A[/COLOR] {
Type type;
[COLOR=var(--highlight-namespace)]int[/COLOR] prop1;
[COLOR=var(--highlight-literal)]A[/COLOR]([COLOR=var(--highlight-namespace)]int[/COLOR] v) : [COLOR=var(--highlight-literal)]type[/COLOR](Type::A), [COLOR=var(--highlight-literal)]prop1[/COLOR](v) {[COLOR=var(--highlight-literal)]addobj[/COLOR]([COLOR=var(--highlight-keyword)]this[/COLOR]);}
};
[COLOR=var(--highlight-keyword)]struct[/COLOR] [COLOR=var(--highlight-literal)]B[/COLOR] {
Type type;
[COLOR=var(--highlight-namespace)]int[/COLOR] prop1;
[COLOR=var(--highlight-literal)]B[/COLOR]([COLOR=var(--highlight-namespace)]int[/COLOR] v) : [COLOR=var(--highlight-literal)]type[/COLOR](Type::B), [COLOR=var(--highlight-literal)]prop1[/COLOR](v) {[COLOR=var(--highlight-literal)]addobj[/COLOR]([COLOR=var(--highlight-keyword)]this[/COLOR]);}
};
[COLOR=var(--highlight-keyword)]struct[/COLOR] [COLOR=var(--highlight-literal)]C[/COLOR] {
Type type;
[COLOR=var(--highlight-namespace)]int[/COLOR] prop1;
[COLOR=var(--highlight-literal)]C[/COLOR]([COLOR=var(--highlight-namespace)]int[/COLOR] v) : [COLOR=var(--highlight-literal)]type[/COLOR](Type::C), [COLOR=var(--highlight-literal)]prop1[/COLOR](v) {[COLOR=var(--highlight-literal)]addobj[/COLOR]([COLOR=var(--highlight-keyword)]this[/COLOR]);}
};
A* [COLOR=var(--highlight-literal)]getA[/COLOR]([COLOR=var(--highlight-namespace)]int[/COLOR] id) {[COLOR=var(--highlight-keyword)]return[/COLOR] (A*)objs[id];}
B* [COLOR=var(--highlight-literal)]getB[/COLOR]([COLOR=var(--highlight-namespace)]int[/COLOR] id) {[COLOR=var(--highlight-keyword)]return[/COLOR] (B*)objs[id];} [COLOR=var(--highlight-color)]C* [COLOR=var(--highlight-literal)]getC[/COLOR]([COLOR=var(--highlight-namespace)]int[/COLOR] id) [/COLOR][COLOR=var(--highlight-color)]{[/COLOR][COLOR=var(--highlight-keyword)]return[/COLOR][COLOR=var(--highlight-color)] (C*)objs[id];}[/COLOR]
In addition, there is "polymorphic" property access, which is allowed to change:
Code:
[COLOR=var(--highlight-color)][COLOR=var(--highlight-namespace)]int[/COLOR]& [COLOR=var(--highlight-literal)]prop1ref[/COLOR]([COLOR=var(--highlight-namespace)]int[/COLOR] id) [/COLOR][COLOR=var(--highlight-color)]{[/COLOR]
[COLOR=var(--highlight-literal)]switch[/COLOR] (objs[id]->type) {
[COLOR=var(--highlight-keyword)]case[/COLOR] Type::A: [COLOR=var(--highlight-keyword)]return[/COLOR] [COLOR=var(--highlight-literal)]getA[/COLOR](id)->prop1;
[COLOR=var(--highlight-keyword)]case[/COLOR] Type::B: [COLOR=var(--highlight-keyword)]return[/COLOR] [COLOR=var(--highlight-literal)]getB[/COLOR](id)->prop1;
}
[COLOR=var(--highlight-keyword)]return[/COLOR] [COLOR=var(--highlight-literal)]getC[/COLOR](id)->prop1;
}
[COLOR=var(--highlight-namespace)]void[/COLOR] [COLOR=var(--highlight-literal)]test[/COLOR]() {
A [COLOR=var(--highlight-literal)]a[/COLOR]([COLOR=var(--highlight-namespace)]1[/COLOR]); B [COLOR=var(--highlight-literal)]b[/COLOR]([COLOR=var(--highlight-namespace)]2[/COLOR]); C [COLOR=var(--highlight-literal)]c[/COLOR]([COLOR=var(--highlight-namespace)]3[/COLOR]);
[COLOR=var(--highlight-keyword)]for[/COLOR] ([COLOR=var(--highlight-namespace)]int[/COLOR] id=[COLOR=var(--highlight-namespace)]0[/COLOR]; id<count; id++)
[COLOR=var(--highlight-literal)]prop1ref[/COLOR](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.