views:

534

answers:

3

This question came to my mind, when I had something like

enum Folders {FA, FB, FC};

and wanted to create an array of containers for each folder:

ContainerClass*m_containers[3];
....
m_containers[FA] = ...; // etc.

(Using maps it's much more elegant to use: std::map<Folders, ContainerClass*> m_containers;)

But to come back to my original question: What if I do not want to hard-code the array size, is there a way to figure out how many items are in Folders? (Without relying on e.g. FC being the last item in the list which would allow something like ContainerClass*m_containers[FC+1] if I'm not mistaken.)

+1  A: 

Add a entry, at the end of your enum, called Folders_MAX or something similar and use this value when initializing your arrays.

ContainerClass* m_containers[Folders_MAX];
Kevin
Ahhhhhhh. My eyes hurt. Who let the Java developer in. Seriously: no need to use new in this context. In fact given the original question this would be incorrect. As you have created an array of ContainerClass while the original question has an array of pointers to ContainerClass.
Martin York
Wow, I'm offended. You owe me a bottle of water for all the tears I've shed because of this remark. I haven't used Java in years :(But yeah.. it was only an example. Since you are right and I don't want to get sued for hurting your eyes, I'll change my example right away! Thank you good sir.Oh, and I want evian if possible, please.
Kevin
You will find better a cleaner water by running the tap. Please help yourself to all the water you need.
Martin York
+15  A: 

There's not really a good way to do this, usually you see an extra item in the enum, i.e.

enum foobar {foo, bar, baz, quz, FOOBAR_NR_ITEMS};

So then you can do:

int fuz[FOOBAR_NR_ITEMS];

Still not very nice though.

But of course you do realize that just the number of items in an enum is not safe, given e.g.

enum foobar {foo, bar = 5, baz, quz = 20};

the number of items would be 4, but the integer values of the enum values would be way out of the array index range. Using enum values for array indexing is not safe, you should consider other options.

edit: as requested, made the special entry stick out more.

wich
Call it LAST or ALWAYS_AT_END or something not so cryptic. Make it __stick out__. So that subsequent maintainers don't accidentally add new entries after you end marker.
Martin York
For better or worse, this is the approach we take in our organization. We normally call it FINAL_enumname_ENTRY, such as FINAL_foobar_ENTRY. I've also seen people use a separate static const FOOBAR_COUNT variable defined right after the enum declaration, an approach that is slightly more error prone.
Darryl
+1  A: 

For C++, there are various type-safe enum techniques available, and some of those (such as the proposed-but-never-submitted Boost.Enum) include support for getting the size of a enum.

The simplest approach, which works in C as well as C++, is to adopt a convention of declaring a ...MAX value for each of your enum types:

enum Folders { FA, FB, FC, Folders_MAX = FC };
ContainerClass *m_containers[Folders_MAX + 1];
....
m_containers[FA] = ...; // etc.

Edit: Regarding { FA, FB, FC, Folders_MAX = FC} versus {FA, FB, FC, Folders_MAX]: I prefer setting the ...MAX value to the last legal value of the enum for a few reasons:

  1. The constant's name is technically more accurate (since Folders_MAX gives the maximum possible enum value).
  2. Personally, I feel like Folders_MAX = FC stands out from other entries out a bit more (making it a bit harder to accidentally add enum values without updating the max value, a problem Martin York referenced).
  3. GCC includes helpful warnings like "enumeration value not included in switch" for code such as the following. Letting Folders_MAX == FC + 1 breaks those warnings, since you end up with a bunch of ...MAX enumeration values that should never be included in switch.
switch (folder) 
{
  case FA: ...;
  case FB: ...;
  // Oops, forgot FC!
}
Josh Kelley
Excellent solution that I've never seen before. I was in the middle of suggesting a Boost.Preprocessor hack that I've used, but this is way more elegant (and what I've been looking for).
Travis Gockel
Why not do: `enum Folders { FA, FB, FC, Folders_MAX }; ContainerClass *m_containers[Folders_MAX];` ?
Bill
I prefer to make clear that the last is a number, and they all have the same name thanks to: `struct SomeEnum { enum type {FA, FB, FC, NB__};};`
Luc Hermitte
wich