I have a peculiar problem. I want to create classes with variable length arrays in them. I don't want to allocate the arrays on the heap for the reasons of locality (the code slows down by a factor of 2 when I do). I don't want to use a virtual function because I don't want to pay for a function call. The following code works (on my compiler/platform), but with a caveat.
include <iostream>
include <boost/array.hpp>
struct Base
{
Base(size_t s):
size(s) {}
int& up(size_t i) { return *(reinterpret_cast<int*>((&size) + 1) + i); }
size_t size;
};
template<size_t sz>
struct Derived: public Base
{
boost::array<int, sz> data;
Derived(): Base(sz) {}
};
int main()
{
Derived<5> d5;
d5.data[2] = 1234;
Base* b = &d5;
std::cout << b->up(2) << std::endl;
}
This is incredibly ugly; the reinterpret_cast<...> is a red flag. Moreover, the caveat is that this fails if I change size_t
to, say, short unsigned
(I guess the compiler pads the class).
So the question is: is there a way to make this portable? Is there a way to determine from Base
where the first member variable will sit in its derived class?
Just an idea that came to my mind: let the Derived
constructor store a pointer to its data inside a Base
member.
struct Base
{
protected:
size_t size;
int * array;
Base(size_t s, int * arr):
size(s), array(arr)
{ }
public:
int& up(size_t i) { return array[i]; }
size_t getSize() { return size; }
};
template<size_t sz>
struct Derived: public Base
{
std::array<int, sz> data;
Derived():
Base(sz, &data[0])
{ }
};
int main()
{
Derived<5> d5;
d5.data[2] = 1234;
Base* b = &d5;
std::cout << b->up(2) << std::endl;
}