liveBook · Manning

Enum

As explained in 100 C++ Mistakes and How to Avoid Them

An enumeration is a C++ type that defines a set of named integral values representing a finite collection of alternatives.

An enumeration names the finite alternatives represented by integral values. The practical mistake is placing unrelated enum constants in the global namespace: duplicate names become errors, while integer backing can let unrelated color sets mix ambiguously. section 4.2

Listing 4.3 Problematic global namespace enumerations
enum TrafficColor {
    Green,
    Yellow,                                                #1
    Red                                                    #2
};
 
enum PaintColor {
    Gray,
    White,                                                 #3
    Black,
    Paint_Red,                                             #4
    Blue,
    Paint_Yellow,
    Paint_Green
};
 
int main() {
    int color = 2;                                         #5
    switch (color) {
    case Red:
        std::cout << "we have a red one\n";
        break;
    case Blue:
        std::cout << "we have a blue one\n";
        break;
    case Yellow:
        std::cout << "we have a yellow one\n";
        break;
    default:
        std::cout << "we have a white one\n";
        break;
    // case White:                                         #6
    };
    return 0;
}

A traffic-light and automobile-paint example shows how global names force weakened names such as Paint_Red and leave an integer color value unclear. section 4.2

Prefer scoped enumerations with enum class. Use values such as Traffic::Yellow and Paint::Blue, and qualify switch cases explicitly. Separate scopes preserve meaningful names and make the selected enum set visible; retain legacy code cautiously and fix it incrementally with testing. section 4.2

Listing 4.4 Separate namespace enumerations
enum class Traffic {                                     #1
    Green,
    Yellow,
    Red
};
 
enum class Paint {                                       #2
    Gray,
    Black,
    White,
    Red,
    Blue,
    Yellow,
    Green
};
 
int main() {
    auto color = Traffic::Yellow;                        #3
    switch (color) {
    case Traffic::Red:                                   #4
        std::cout << "we have a red light\n";
        break;
    case Traffic::Yellow:
        std::cout << "we have a yellow light\n";
        break;
    case Traffic::Green:
    default:
        std::cout << "we have a green light\n";
        break;
    };
 
    Paint can = Paint::Blue;
    switch (can) {
    case Paint::Red:
        std::cout << "we have a red cube\n";
        break;
    case Paint::Yellow:
        std::cout << "we have a blue cube\n";
        break;
    case Paint::White:
        [[fallthrough]];    
    default:                                             #5
        std::cout << "we have a white cube\n";
        break;
    };
    return 0;
}

The corrected example separates Traffic and Paint, then switches over qualified enumerators without renaming colors to avoid collisions. section 4.2

How 100 C++ Mistakes and How to Avoid Them covers it

How deep it goes
Explains global-name collisions, integer ambiguity, default values, and scoped corrections through contrasting code listings.
Examples
Uses traffic-light colors, automobile paint colors, integer color values, and separate Traffic and Paint enums.
What it assumes
Assumes variables, constants, and switch statements while teaching symbolic alternatives from their practical motivation.
What you can do after
Apply it via enum class to separate related value sets and write qualified switch cases.
How it connects
Connects enumerations with namespaces, integers, switch statements, and qualified names.

Also explained in

Compare how 23 books explain enum →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 C++ Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.