Specifically, I would like to be able to use polymorphism without heap allocation in an embedded context (thus without dynamic allocation). My concern here seems to be that accessing the base
member while x
or y
are "active" in the union seems to be an instance of type-punning, even though they share the same initial header (and vtable structure). Would the code below be considered defined behavior?
#include <iostream>
#include <new>
using namespace std;
struct Base {
virtual const char *foo() { return "base"; }
};
struct X: public Base {
const char *foo() override { return "d1"; }
};
struct Y: public Base {
const char *foo() override { return "d2"; }
};
union DerivedAny {
DerivedAny() {}
Base& get() { return *launder(&b); }
Base b = {};
X x;
Y y;
};
DerivedAny objs[3];
int main() {
new (&objs[1].x) X;
new (&objs[2].y) Y;
cout << objs[0].get().foo() << endl;
cout << objs[1].get().foo() << endl;
cout << objs[2].get().foo() << endl;
}
I've compiled it with both GCC and Clang and they to appear to return the expected output in both cases:
base
d1
d2
std::variant
andvisit
? – Vaios