This is but one way I've seen it done (and used it), ugly as the casting is
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
struct Obj
{
int n;
int *a;
Obj( int sz )
: n( sz )
{
a = reinterpret_cast< int * >(reinterpret_cast< char * >(this) + sizeof( Obj ));
}
};
int main()
{
constexpr int ArrSize = 50;
constexpr int BufSize = sizeof(Obj) + ArrSize * sizeof(int);
char buf[ BufSize ];
Obj *o = ::new (buf) Obj( ArrSize );
o->a[49] = 5;
return 0;
}
|
Though this approach treats "a" as a mere convenience, replacing what would otherwise have been a dynamically allocated array (using new int[ n ] );
That's the view of Node in make_shared of shared_ptr, where the node typically has a pointer to an object allocated with new, and that is used to reference the block beyond the end of the node, as the array is here.
That is not, granted, exactly what flexible arrays are in C, but a related notion.
A different version is to ignore any kind of pointer in the Obj class, but use an access function (a get) to calculate the pointer appropriate for the storage (merely sizeof( obj ) + this). This would more closely resemble the actual layout of the flexible arrays of c.
It isn't that the lexical convenience is implemented, but that object layout can be achieved, and so from a practical perspective the same kind of thing can be created where the objective is one block of RAM used for the "invention". For C++, a vector may be more appropriate, but if the objective is to consolidate storage and cut the second allocation (as it is with make_shared), these are the lines of thought which do that.