An enumeration variable has some special properties, which we’ll examine now.
The only valid values that you can assign to an enumeration variable without a type cast are the enumerator values used in defining the type. Thus, we have the following:
band = blue; // valid, blue is an enumerator
band = 2000; // invalid, 2000 not an enumerator
Thus, a spectrum variable is limited to just eight possible values. Some compilers issue a compiler error if you attempt to assign an invalid value, whereas others issue a warning. For maximum portability, you should regard assigning a non-enum value to an enum variable as an error.
Only the assignment operator is defined for enumerations. In particular, arithmetic operations are not defined:
band = orange; // valid
++band; // not valid, ++ discussed in Chapter 5
band = orange + red; // not valid, but a little tricky
...
However, some implementations do not honor this restriction. That can make it possible to violate the type limits. For example, if band has the value ultraviolet, or 7, then ++band, if valid, increments band to 8, which is not a valid value for a spectrum type. Again, for maximum portability, you should adopt the stricter limitations.
Enumerators are of integer type and can be promoted to type int, but int types are not converted automatically to the enumeration type:
int color = blue; // valid, spectrum type promoted to int
band = 3; // invalid, int not converted to spectrum
color = 3 + red; // valid, red converted to int
...
Note that in this example, even though 3 corresponds to the enumerator green, assigning 3 to band is a type error. But assigning green to band is fine because they are both type spectrum. Again, some implementations do not enforce this restriction. In the expression 3 + red, addition isn’t defined for enumerators. However, red is converted to type int, and the result is type int. Because of the conversion from enumeration to int in this situation, you can use enumerations in arithmetic expressions to combine them with ordinary integers, even though arithmetic isn’t defined for enumerations themselves.
The earlier example
band = orange + red; // not valid, but a little tricky
fails for a somewhat involved reason. It is true that the + operator is not defined for enumerators. But it is also true that enumerators are converted to integers when used in arithmetic expressions, so the expression orange + red gets converted to 1 + 0, which is a valid expression. But it is of type int and hence cannot be assigned to the type spectrum variable band.
You can assign an int value to an enum, provided that the value is valid and that you use an explicit type cast:
band = spectrum(3); // typecast 3 to type spectrum
What if you try to type cast an inappropriate value? The result is undefined, meaning that the attempt won’t be flagged as an error but that you can’t rely on the value of the result:
band = spectrum(40003); // undefined
(See the section “Value Ranges for Enumerations,” later in this chapter for a discussion of what values are and are not appropriate.)
As you can see, the rules governing enumerations are fairly restrictive. In practice, enumerations are used more often as a way of defining related symbolic constants than as a means of defining new types. For example, you might use an enumeration to define symbolic constants for a switch statement. (See Chapter 6, “Branching Statements and Logical Operators,” for an example.) If you plan to use just the constants and not create variables of the enumeration type, you can omit an enumeration type name, as in this example:
enum {red, orange, yellow, green, blue, violet, indigo, ultraviolet};
Setting Enumerator Values
You can set enumerator values explicitly by using the assignment operator:
enum bits{one = 1, two = 2, four = 4, eight = 8};
The assigned values must be integers. You also can define just some of the enumerators explicitly:
enum bigstep{first, second = 100, third};
In this case, first is 0 by default. Subsequent uninitialized enumerators are larger by one than their predecessors. So, third would have the value 101.
Finally, you can create more than one enumerator with the same value:
enum {zero, null = 0, one, numero_uno = 1};
Here, both zero and null are 0, and both one and numero_uno are 1. In earlier versions of C++, you could assign only int values (or values that promote to int) to enumerators, but that restriction has been removed so that you can use type long or even long long values.
Value Ranges for Enumerations