Reputation: 19384
I've got a static map of identifier<=>struct pairs, and each struct should contain some arrays. Everything is known at compile time. That is, I want to have something like this here:
ID1 => name: someString
flagCount: 3
flags: [1, 5, 10]
statically created (if possible). Of course, a declaration like:
struct Info
{
const char* name;
int flagCount;
int flags[];
};
would be ideal, as long as I could initialize it like ...
Info infos [] = { ... };
which is not possible, due to the varying length arrays (except I'm missing something). Alternatively, I though about (ab)using boost::assign
for this, but I'm wondering if there is a recommended solution to this. I'm fine if I can store only the info structures into an array, and to the mapping elsewhere.
Edit: A note on the current solution. At the moment, I have:
struct Info
{
Info (const std::vector<int>& flags) : flags {}
std::vector<int> flags;
};
and I use:
const std::map<ID, Info> map = boost::assign::map_list_of
("ID1", Info (boost::assign::list_of (1)(2)(3));
which works, I'm just curious whether there is a simpler solution (template-based?).
Upvotes: 0
Views: 436
Reputation: 40336
Using a vector as you have done is almost certainly the best solution. oefe has given you a solution where you include some indirection in the Info's themselves, another option is to indirect in the map, i.e. map<ID, Info*>
(or since you're using boost map<ID, shared_ptr<Info> >
) and define Info like. Actually don't do this. Use a vector. It's the best solution.
struct Info {
const char *name;
int flagCount;
int flags[1]; // this is cheating...
};
Info* make_info(int count) {
char *buf = new char[sizeof(Info) + (sizeof(int) * (count - 1))];
Info *rv = static_cast<Info*>(static_cast<void*>(buf));
rv->flagCount = count;
}
Upvotes: 1
Reputation: 19916
Either use a pointer to the variable-length array:
struct Info
{
const char* name;
int flagCount;
int *flags;
};
or fixed-size array large enough to hold all flags:
struct Info
{
const char* name;
int flagCount;
int flags[MAX_FLAGS];
};
Both solutions will waste some memory; but for solution 1, it's just one pointer per struct; note that you are already implicitly using this solution for the name field.
Upvotes: 1
Reputation: 49311
The elements in an array must be the same size as each other, otherwise you can't use infos[i]
to access them - the compiler would have to step through the array and look at the size of each element up to i
to find where the next one started. You can allocate enough memory for each element contiguously, and then create an array of pointers to the elements (pointers being a fixed size). If you only need the mapping and not to index the infos then your map will be identifier to pointer.
Alternatively, as you know the size at compile time, if there are only a few flags, make the Info::flags
array large enough for the maximum flags, or make it a pointer to an array of flags, so that Info is a fixed size struct.
Upvotes: 1