I've been dealing with this problem today and found a solution for it, though I can't stress enough how dangerous this solution may be (see below why it's dangerous).
My particular problem was that I just wanted to extend a library struct with some methods of my own. I wanted to keep it POD with exactly the same layout as base since I wanted to use functions that take base as parameter.
The solution goes like this:
#include <iostream>
using namespace std;
struct BASE {
int x, y;
};
struct FOO: BASE {
void Foo() { x = y = 1; }
};
int main() {
// const declaration
const BASE a = { 0, 1 };
const FOO &b = *reinterpret_cast<const FOO *> (&a);
// non-const declaration
BASE _a = { 0, 3 };
FOO &c = *reinterpret_cast<FOO *> (&_a);
cout << "base: " << a.x << ", " << a.y << endl;
cout << "foo 1: " << b.x << ", " << b.y << endl;
cout << "foo 2: " << c.x << ", " << c.y << endl;
return 0;
}
However, note that this only works because the data layout between BASE and FOO is the same. Also only because I use pointers to cast to FOO type. In this case the type casting is done without any constructors, it just pretends that the memory is in correct format. If you try to reinterpret_cast without pointers, the compiler will instead try to construct a new object based on original.
See this answer for better explanation.
Unfortunately, there doesn't seem to be a nice one-liner for this. A proper macro for declarations seems in order.