Enumerators and Their Values in C++
Whenever you read an enumerator in code, the qualified name tells you which enumerator it is. Follow the qualifier before the :: rather than the bare word red.
Two Different Things Called red
Imagine you are building a small program that tracks two things: the color of a paint sample and the state of a traffic light. Both sets of choices seem to need a word called red. It is tempting to believe that red is simply red, one fixed thing that means the same everywhere in the program. This belief is the misconception this article addresses.
What do you think happens?
Two enum classes are declared: one named Color with red, blue, and green, and one named Traffic_light with green, yellow, and red. Are Color::red and Traffic_light::red the same enumerator, or two separate enumerators that share a spelling?
Reveal answer
They are two separate enumerators that happen to share the spelling red.
Enumerators are in the scope of their enum class, so the same name can appear in different enum classes without confusion. The enum class name in the qualified name tells you which enumerator is meant.
Keep this prediction in mind. The rest of the article traces how C++ decides which red a given line of code means.
Why the Same Spelling Does Not Clash
The source gives the reason for this design directly. Because enumerators such as red are in the scope of their enum class, they can be reused in different enum classes without confusion. Reusing the word red does not force the programmer to invent a new spelling such as colorRed or lightRed. Each enum class keeps its own list, and the qualified name tells the compiler which list you mean.
A helpful way to picture this is as containers. Each enum class is a container that holds its own enumerators. The word red appears inside the Color container and again inside the Traffic_light container. Those are two entries in two different places, and the container that holds each one is what distinguishes them.
Declaring an enum class
An enum class declares a named set of enumerators inside braces. It is written with the keywords enum class, followed by a name, and then a braced list of enumerators separated by commas.
- enum class: the keywords that start the declaration
- Color: the name of the enum class
- { red, blue, green }: the braced list of enumerators
- The commas separate the enumerators, and the semicolon ends the declaration
The declaration above creates three enumerators: red, blue, and green. Each one belongs to the Color enum class. The source also declares a second enum class with the same kind of structure: enum class Traffic_light { green, yellow, red };. The two lists are independent, so Color and Traffic_light each keep their own set of names.
Reading a Qualified Name
To use an enumerator, you write the enum class name, the scope operator ::, and the enumerator name. The source uses the following line to create a variable of type Color and set it to the red enumerator.
- Color on the left: declares that the variable col has type Color
- Color::red on the right: names the specific red enumerator inside Color
The name Color on the left declares the variable type. The name Color::red on the right names one particular enumerator. Read the qualifier before the :: as the question of which list you are looking in. Only after that does the bare word red pick out an entry.
Whenever you read an enumerator in code, the qualified name tells you which enumerator it is. Follow the qualifier before the :: rather than the bare word red.
Tracing Both Enum Classes Together
- The first two lines declare two independent enum classes
- The last two lines each create a variable and set it using a qualified name
Tracing which red each line means
In the program above, which enumerator does Color::red refer to, and which enumerator does Traffic_light::red refer to?
- 1Find the qualifier
In Color::red, the qualifier is Color. In Traffic_light::red, the qualifier is Traffic_light.
- 2Look inside that enum class
Color::red looks only in the list { red, blue, green }. Traffic_light::red looks only in the list { green, yellow, red }.
- 3Select the matching entry
Each list contains a red entry, and the qualifier chooses which one is meant.
- 4Compare the two results
The two results are separate enumerators. They share a spelling but belong to different enum classes.
Color::red is the red enumerator of Color, and Traffic_light::red is the red enumerator of Traffic_light. They are different enumerators, even though both are spelled red.
Where One Enum Class Ends
The braces of an enum class mark its scope. The names listed between the braces belong to that enum class and are visible through its qualified names. In the program above, the braces of Color hold red, blue, and green, and the braces of Traffic_light hold green, yellow, and red. When a line of code is outside those braces, the bare names inside them are not what the line refers to; the line refers to them through the enum class name.
Mistakes Beginners Make with Qualified Names
Common mistake Assuming red is one fixed thing that means the same everywhere
What it looks likeReading the line Traffic_light light = Traffic_light::red; and thinking it refers to the same value as Color::red.
Why it failsEach enum class has its own list, and the two red entries are separate enumerators.
Do this insteadRead the qualifier first and identify which enum class owns the name.
Common mistake Tracing a program by stopping at the bare word red
What it looks likeFollowing a trace through the line Color col = Color::red; and writing down just red without the Color qualifier.
Why it failsA trace that stops at red and forgets Color or Traffic_light is where the misconception usually causes a wrong conclusion.
Do this insteadKeep the full qualified name, including the enum class name and the :: operator, in every step of the trace.
Common mistake Inventing new spellings to avoid a clash
What it looks likeRenaming the traffic light entry to lightRed so that it does not match the color entry.
Why it failsEnumerators in different enum classes do not clash, so the renaming is unnecessary.
Do this insteadReuse the natural name and rely on the qualified name to tell the enumerators apart.
Checking Your Reading of Qualified Names
Given the two enum classes enum class Color { red, blue, green }; and enum class Traffic_light { green, yellow, red };, state which enumerator each of these names refers to: Color::green, Traffic_light::green, and Traffic_light::red. Explain your answer by pointing to the qualifier in each name.
Hints
- Look at the word before the :: first.
- Check which braced list contains the bare name that follows the ::.
Write two lines of code that declare a variable of type Color and a variable of type Traffic_light, and set each one to its red enumerator. Then write one sentence explaining why the two red values do not clash.
Hints
- Use the pattern Type name = Type::enumerator; for each variable.
- The sentence should mention the scope of each enum class.
Key Takeaways
- An enum class declares a named set of enumerators inside braces, such as enum class Color { red, blue, green };
- Enumerators are in the scope of their enum class, so the same name, such as red, can appear in different enum classes without confusion.
- Color::red and Traffic_light::red are different enumerators, even though both are spelled red.
- To read or trace an enumerator, follow the qualifier before the :: and keep the enum class name with the enumerator name.