Boost logo

Boost :

From: Paul Tozour (paultoz_at_[hidden])
Date: 1999-12-10 03:21:01


Forgive me if this issue has come up before; I'm new to the Boost discussion
group.

A lot of my work deals with enumerated types. Unfortunately, enumerated
types are very much a dark back corner of the language at the moment.
Although they are hugely useful for a number of tasks, they lack a number of
the basic features one would expect from such a language feature.

For example, there is no way (unless I'm missing something obvious) to
iterate over an enumerated type (at least, there is no built-in language
support for this). One would think that since it's called an "enumerated"
type, you could at least enumerate its elements, but you can't. You also
cannot find the first or last element of an enumerated type, query
membership, etc. Being able to query the validity of an enumerated type is
especially important as one often saves enumerated types to data files, and
it's impossible to validate the data when you read it in again unless you
have some way of ensuring that the enumerated type value you're reading in
is really a part of that type.

In short, enumerated types seem to be begging for the capabilities of an STL
container.

For example, if I had an enumerated type, it would be great if I could just
declare a wrapper class which immediately contain all of the elements of the
enumerated type upon construction.

e.g., if I had an enum called Color, I'd like to be able to just say:

        std::enum_container<Color> all_colors;

Clearly, I can get what I need by wrapping my own container around the enum
like so:

        enum Color
        {
                RED,
                GREEN,
                BLUE
        };

        void main()
        {
                std::vector<Color> color_wrapper;
                color_wrapper.push_back (RED);
                color_wrapper.push_back (GREEN);
                color_wrapper.push_back (BLUE);
        }

"color_wrapper" now contains all the elements of the enumerated type Color.
I can iterate over it, use std::find, and generally be happy. It's also
nice and type-safe. Of course, I have to do this manually for each and
every enumerated type.

An obvious kludge comes to mind. You could use #defines like so:

        enum Color
        {
                RED,
                GREEN,
                BLUE
        };

        enum
        {
                COLOR_FIRST = RED,
                COLOR_LAST = BLUE
        };

        #define
ENUM_VECTOR(vector_name,enum_type,first_element,last_element) \
                std::vector<enum_type> vector_name;
\
                for (int i = (int)first_element; i <= last_element; ++i)
\
                        vector_name.push_back((enum_type)i);

and use it like this:

        ENUM_VECTOR(my_color_vector,Color,COLOR_FIRST,COLOR_LAST);

(Obviously, this is a nasty kludge, and it would be better to create your
own container class which internally used a std::vector and accepted the
first and last enum elements as arguments to the constructor. But this
example was a lot shorter, and in any case, both achieve the desired
effect.)

Unfortunately, it wouldn't always work. The example above relies on the
assumption that enumerated types are sequential. For example, if I had an
enum like this:

        enum EvenNumbersLessThanTen
        {
                TWO = 2,
                FOUR = 4,
                SIX = 6,
                EIGHT = 8
        };

then trying to use my ENUM_VECTOR kludge would also stuff the enumerated
type values for 3, 5, and 7 into the vector, which are invalid.

What does everyone think of this? Is anyone aware of a reasonable, generic
solution to this problem?

If not, given that this could be implemented without breaking any existing
code or modifying the current design of enumerated types, IMHO it should be
simple enough to add it as a language extension in the next rev of C++.

PT


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk