[net.lang.c] How should 'enum's work?

kpmartin@watmath.UUCP (Kevin Martin) (10/25/84)

Subject: Enums: What should they do?
Newsgroups: net.lang.c

Here are my ideas on the way ENUM's should work. Some compilers are more
strict than this description, others are more lax.

An operation on a enum acts like the same operation on an int of the
same value. If the operation happens to yield an integer which does not
have a corresponding identifier in the enum list, tough. This can happen
either because the user has run off the end of a list (i.e. lack of
bounds checking), or the user has used explicit values to generate gaps
in the valid enum values.

The operations
   ++enum
   enum++
   --enum
   enum--
   enum += int
   enum -= int
   enum = enum_of_same_type
   &enum
are allowed on enum lvalues.

The expressions
   enum + int
   enum - int
yield an enum of the same type.
 
When an enum is wanted as an array subscript, or dimension, it is
implicitly converted to int. Similarly for adding a pointer to an enum.

Integral expressions are automatically promoted to enum if needed.

For assignment to an enum and compares between enums, both operands
must be of the same enum type (or a promoted int).  Similarly, when
switching on an enum, the case constants must be either integral, or
enum of the correct type.

In other cases where the programmer wants to convert int<->enum or
between enum types, explicit casts may be used.


Basically, this model does enum's similar to Pascal's enumerated types:
You can take the predecessor/successor (or the n'th pred/succ), you
can assign them, compare them, and subscript them. The main difference is
that the inverse of Pascal's ORD function need not be explicitly coded.

I have less sympathy for programmers who assign sparse values to enums,
then expect that ++ will continue to act like SUCC in Pascal.
Also, consider having valid values for a number, say from 1 to 100. The
values 1, 42, and 86, and 99 are important, and you want to name these
4 values with a sparse enum type. You shouldn't have to name all 96 other
values just so that ++ works the way you want it to.  (although you should
have to name 100 to ensure that the variable has enough range)

---->Start of flame-thrower target range<----
If you want to get fancy, you could enforce that *only* the enum type
used in the dimension of an array declaration may be used to subscript
that particular array...

The conversion of an enum to char * through a direct cast should yield
a string giving the enum identifier. (or some fault if you try to convert
a value that's doesn't have a matching enum identifier)
--:-) End of flahe-thrower target range (-:--

                    Kevin Martin, UofW Software Development Group

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (10/29/84)

> ... (although you should
> have to name 100 to ensure that the variable has enough range)

I like all Kevin's suggestions on enums before this one.  enum++
where there is no "next" value is no worse than pointer++.  Perhaps
pointer++ past the valid range should be outlawed (I have seen it
cause subtle bugs, including in the PDP-11 C compiler), but doing
this would outlaw a vast amount of existing code.

> If you want to get fancy, you could enforce that *only* the enum type
> used in the dimension of an array declaration may be used to subscript
> that particular array...

Eh?  What syntax for array declarations are we talking about here?

> The conversion of an enum to char * through a direct cast should yield
> a string giving the enum identifier.

This would require storing all the enum names in run-time data space.
It would also be a rule unlike any other in C.  I vote against this one.

kpmartin@watmath.UUCP (Kevin Martin) (10/30/84)

>>I wrote:
>Doug Gwyn writes:
>> ... (although you should
>> have to name 100 to ensure that the variable has enough range)
>
>I like all Kevin's suggestions on enums before this one.
The intent of my comment about the 100 was indeed merely a note that
the programmer must define the entire range, as well as the values he
actually cares about.
Otherwise, some clever compiler-writer might do some excessive bit-cramming
(I don't know what either ANSI or various C compilers do about this)

>> If you want to get fancy, you could enforce that *only* the enum type
>> used in the dimension of an array declaration may be used to subscript
>> that particular array...
>Eh?  What syntax for array declarations are we talking about here?
	enum primary {red, green, blue};
	enum complementary {cyan, magenta, yellow};
	int x[blue];	/* can only be subscripted with 'primary's */
	int y[yellow];	/* can only be subscripted with 'complementary's */
Of course, the above wouldn't give quite enough space in the array. That's
why the comment was only semi-serious.

>> The conversion of an enum to char * through a direct cast should yield
>> a string giving the enum identifier.
>This would require storing all the enum names in run-time data space.
>It would also be a rule unlike any other in C.  I vote against this one.
You only have to store the names if someone actually uses such a cast.
How about casting into (char []) instead of (char *) ? :-)

                       Kevin Martin, UofW Software Development Group