Enumerations are a great idiom. They allow you to define a
type that is composed of a predefined set of values. The code becomes easier to
write, and test, is more readable, and is easier to maintain–benefits you’re
likely to love. For example, check out the listing below; by reading the code,
you’ll instantly understand that the first working day is Monday:
enum week_day {
Mon, Tue, Wed, Thu, Fri, Sat, Sun
};
week_day first_work_day;
first_work_day = Mon;
However, programmers need to deal with large amounts of
code, in the order of hundreds of thousands to millions of lines. Therefore,
it’s very easy for you to forget names (of functions, classes, namespaces,
etc). Code-completion is a great tool to help programmers deal with the
plethora of names in current code—a feature most IDEs implement
in some fashion.
Code-completion
Code-completion helps programmers by showing them possible
ways to complete instruction(s). Type a few letters, and the environment
suggests one or more possibilities to complete the current instruction, similar
to what is shown in Figure A.
Figure A |
![]() |
A typical code-completion |
The problem with code-completion is that it does not work
for enumerations. More to the point, when dealing with an enumerated type, how
do you know what set of values it’s composed of? You would like something
similar to Figure B.
Figure B |
![]() |
Enumerated completion |
Unfortunately, this does not happen in any IDE I know of at
this time, and it’s very unlikely it will happen anytime soon. The good news is
that you can get pretty close to that using the following technique.
Namespaces vs. structures
In order to allow code-completion, simply surround your
enumeration in a namespace
or a struct. You’ll name the
structure/namespace as your enumeration, and give your enumeration a new name
(the simplest would be to call it type). An example is shown in Figure C.
Figure C |
![]() |
Namespace/struct |
It’s that simple! Your fellow programmers and those using or
enhancing your code will certainly thank you for it. And the code will be even
more readable—every usage of your enumeration will be prefixed by its type—as
shown here:
// somewhere, in a distant header
namespace show {
enum type {
normal, hide, maximize, minimize, restore
};
};
struct window {
void show( ::show::type s);
// ...
};
int main() {
window w;
// hide the window
w.show(show::hide);
// maximize the window
w.show(show::maximize);
}
An even better benefit is when you have combination
enumerations: where a valid value could be a combination of states, as you see
in Figure D. By reading the code,
you can clearly tell that checked, enabled, and focused are possible states of
a check-box.
Figure D |
![]() |
You implement this technique using either a namespace (as I’ve shown you in the
previous examples), or by using a structure; both have pros and cons. The
advantages of namespaces include:
- A namespace is open; you can add
other new types/definitions to it - When
using a namespace, no unneeded code is generated (when using a struct, some poor compilers might
mistakenly generate the class’s default constructor, etc., even though
they’re never needed) - They
specify your intent in a more clear way: a namespace, as its name suggests, is a place where you collect
names; a structure, on the other hand, is a collection of data. Thus,
using a struct like shown above
might be misleading to some programmers.
The drawbacks of namespaces include:
- They
cannot be used inside a class - You
cannot inherit a namespace, like
you can inherit a structure
In the light of the above, I recommend you use namespaces
where possible, and structures where you must.
When you want to make an enumeration part of a class, you’ll
implement something like this code:
struct check_box {
// CANNOT use a namespace here
struct state {
enum type {
checked = 1, enabled = 2, focused = 4, pressed = 8
};
};
void set_state(int s);
// ...
};
int main() {
check_box c;
c.set_state(check_box::state::checked |
check_box::state::enabled); }
The latter case is quite advanced and somewhat rare. It
occurs when you want to conceptually extend an enumeration, adding one or more
values to it. For example, you might want to add a new check-box state:
hot-tracked. Thus, you will extend the check_box
class, and the state enumeration as shown in Figure E.
Figure E |
![]() |
Extend the enumeration |
Friendly enumerations
Enumerations are a very useful C++ construct. Using the
technique I’ve shown you, you can make them easier to use, read, and maintain.
In a word: friendlier.