Having the following structures:
class XY
{
private:
int test;
};
class XYZ
{
private:
short extra;
int test;
};
I want to use XY::test
and XYZ::test
depending on a runtime variable. Like:
if (x == 1)
{
reinterpret_cast<XY*>(object)->test = 1;
}
else if (x == 2)
{
reinterpret_cast<XYZ*>(object)->test = 1;
}
Is it possible to make this into a nice one-liner? (using templates, macros, etc...?)
What should I do about &object->test
depending on a different type of object? What if the object is passed into a function like the following?
void Function(void* object)
{
if (x == 1)
{
reinterpret_cast<XY*>(object)->test = 1;
}
else if (x == 2)
{
reinterpret_cast<XYZ*>(object)->test = 1;
}
}
How can I properly deal with this? I have so much code like this, so I can't write an if condition every time. Also, I am unable to change the structures' layout in any way, shape, or form.
Since XY::test
and XYZ::test
are at different byte offsets, and you have stated that you cannot change these structs, I think the best you can do is using an int*
pointer, eg:
int *ptest;
switch (x) {
case 1: ptest = &(static_cast<XY*>(object)->test); break;
case 2: ptest = &(static_cast<XYZ*>(object)->test); break;
...
}
*ptest = 1;
Though, if you really want something more general, an alternative would be to do something like this:
const std:unordered_map<int, size_t> offsets = {
{1, offsetof(XY, test)},
{2, offsetof(XYZ, test)}
...
};
...
*reinterpret_cast<int*>(static_cast<char*>(object) + offsets[x]) = 1;
#define FlexibleOffset(class1, class2, member) (x == 1 ? offsetof(class1, member) : offsetof(class2, member))
#define FlexibleMember(object, member) *reinterpret_cast<decltype(XY::member)*>(reinterpret_cast<uintptr_t>(object) + FlexibleOffset(XY, XYZ, member))
FlexibleMember(object, test) = 1;
void* addressTo = &FlexibleMember(object, test);
If you want to keep the syntax of ->, there is no way but to use this method and declare each of your class members in XYZWrapper:
struct XYZWrapper
{
XYZWrapper(void* ptr)
{
if (x == 1)
{
extra = nullptr; // doesn't exist in x == 1
test = reinterpret_cast<XY*>(ptr)->test;
}
else if (x == 2)
{
extra = reinterpret_cast<XYZ*>(ptr)->extra;
test = reinterpret_cast<XYZ*>(ptr)->test;
}
}
XYZWrapper* operator->() { return this; }
short* extra;
int* test;
}
*XYZWrapper(object)->test = 1;
void* addressTo = XYZWrapper(object)->test;
void SomeFunction(XYZWrapper object)
{
*object->test = 1;
if (x == 2) *object->extra = 4;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With