Quote:
What I usually do to make working with multiple different enum types quick and easy, as well as to avoid name conflicts, is I don't ever use the c++ enum type anymore, but instead use standardized integral types of defined length and format. This, firstly, makes your code much more easily to be portable. Next, I made a templated Enumeration class with 1 template parameter for the [usually] integral type to be used. The class completely consists of inline protected members and overloaded operators, and is simply used as a base from which to derive your "enums."
Then, anytime you want a new type of enumeration, you create a new class for it, use private inheritance on the Enumeration type with the integral template parameter to optimize how much space you need for the type (IE an 8-bit unsigned int if the enumeration only needs a small range of possible values, or even an unsigned 64 bit integer if you are using a very large set of bitflags). Inside the class definition you define public static constants of the template type, which you use to act as your enum constants. Finally, you promote any member functions from the base to be public in the child, picking and choosing which functions to promote depending on whether or not it makes sense to, for instance, incremement an instance.
You still get typesafety, although now on an object level. Also, since the enumerations are all privately derived from the Enum type, you can't convert to the base, which is good, because they should be thought of as completely different types.
So now, whenever you need an enumeration of a certain type, you use the object type. You specify it's value by doing ObjectType::ConstantName. You only use the constant names as temporary objects for construction. You should never explicitly declare an object of the interal type.
The only downside is that it's, of course, possible to construct the object with a different constant if the integral type is the same or if there is a built-in conversion between the types. This only happens during construction because everywhere else, you use the object's type, not the integral type. Also, if you consider other solutions, such as opengl's "super enum," they lack any form of typesafety on enumerations because they use exactly the same type for all of them (of course, since opengl is procedural there wasn't much of a choice)!
Since the constants are public, static and nested in the class definitions, you never have to worry about name conflicts, but you can still access them externally. If you have ever worked with a lot of enumerations, you know what I'm talking about. For instance, it makes sence to have a None constant for many different enumerations which would normally result in conflicts. Since, with my implementation, the constants are encapsulated in their appropriate type definitions, name conflicts are never a problem, so you can have many types with enumerations of the same name, without ever having problems.
Since the integral type is a template parameter, not only do you benefit from control of the size, etc. but it also makes it very simple to work with fileio. When using enum, you have no control of the size of the datatype (unless you use bitfields, though even then, you may have format problems and you have no way of creating a constant of larger size than your compiler's enum). With my implementation, you get low-level control with high-level benefits, and because all of the member functions are inlined, speed should not be an issue.
I know using an int isn't 'correct' because you want your day to be its own data type. It just seems easier to use an int, it is what I would do. I pay a lot for ibuprofen as it is :(