Structs, Enums, and Type Aliases

Enumerations

Often a program needs a handful of named options that are really just related integers. Hardcoding the integers makes the code unreadable and prone to errors. An enumeration provides the names for the options, yet the value can be used just as an integer when required.

An enumeration type defines its set of possible values by providing a list of the names of its enumerators, where the list is enclosed in braces. Each name defined is a constant member of the enumeration type.

#include <iostream>

enum Color
{
    red,
    green,
    blue
};

int main()
{
    Color paint { red };
    std::cout << paint << '\n';

    return 0;
}

In the definition above, a new type called Color is created, and three "named values", called enumerators, are created and given default integer values. The first enumerator has the value 0, the second enumerator 1, etc. Thus, the variable called paint has been defined as a Color, and set to start with the enumerator red.

When paint is displayed as part of the print statement, the output will be 0, as this corresponds to what value the enumerator red was assigned.

The program has thus been able to use the name, red, blue, or green, and still be stored as an ordinary integer.

We can explicitly program the integer values if the default row is not friendly.

#include <iostream>

enum Color
{
    red = 1,
    green = 2,
    blue = 4
};

int main()
{
    Color paint { green };
    std::cout << paint << '\n';

    return 0;
}

At this point, red has value 1, green has value 2, and blue has value 4. The value of paint is green, so the print statement would display 2. Later enumerators that are no longer assigned a value will continue to count up from the previous enumerator; if blue had appeared without the equals clause, then it would have gotten the value 3.

Since the enumerators are normal integer constants, a variable of the enumeration type may be used anywhere an integer is expected.

#include <iostream>

enum Color
{
    red,
    green,
    blue
};

int main()
{
    Color paint { blue };
    int code { paint };

    std::cout << code << '\n';

    return 0;
}

Initialising int code { paint }: The switch from enumerator blue to its underlying type is performed automatically in this statement. Underlying type of blue is 2, not blue itself. The 2 is assigned to code.

The cast is not necessary.

The same conversion applies to an enumerator on passing to a function that requires int, to an arithmetic expression, etc.

The implicit conversion is also convenient but also error prone: an int can be assigned even if it is not strictly an enumerator.

#include <iostream>

enum Color
{
    red,
    green,
    blue
};

int main()
{
    Color paint { 5 };
    std::cout << paint << '\n';

    return 0;
}

The value 5 is happily accepted where no enumerator for it exists. Now the variable paint has an integer which is outside the range of named choices. Later code which assumes it always contains one of the three enumerators may do silly things. For example, the language does not check that an enumerator variable is still within the range of named values; it is up to the programmer.

Enumerations are useful to clarify the purpose of a condition or a choice.

#include <iostream>

enum Color
{
    red,
    green,
    blue
};

void printColor(Color c)
{
    if (c == red)
        std::cout << 0 << '\n';
    else if (c == green)
        std::cout << 1 << '\n';
    else if (c == blue)
        std::cout << 2 << '\n';
}

int main()
{
    printColor(green);

    return 0;
}

A copy of the enumerator green is stored in c. The operations c == red, c == green, and c == blue compare the underlying integer values. As the names are present in the source, the reader need not recall which integer belongs to which color to understand what the program does. This same facility is available when an enumeration is used as the condition of a switch statement.

An enum therefore provides a set of related named constants whose values the program can use as human readable symbolic values, or as ordinary numbers.

Exercise: EnumerationsStarter code, hints and solutionOpenClose
Guided practiceBeginner · 10–15 min

Practice: Enumerations

Work through the mission, reveal hints only when needed, and compare your result with the model solution.

Your challenge

Create a Color variable initialized to blue and pass it to printColor after the original call. Predict its branch and output.

Mission checklist

  1. Run the starter as a baseline, then predict the change requested in Your challenge.
  2. Make that change in your editor; use the lesson-specific hints if you need help.
  3. Compile and run your answer, then compare with the worked solution and explain the result.

Starter program

This is the working baseline, not the completed answer. Compile as C++20, then make the change described above.

#include <iostream>

enum Color
{
    red,
    green,
    blue
};

void printColor(Color c)
{
    if (c == red)
        std::cout << 0 << '\n';
    else if (c == green)
        std::cout << 1 << '\n';
    else if (c == blue)
        std::cout << 2 << '\n';
}

int main()
{
    printColor(green);

    return 0;
}

Hints

Hint 1

Color is an unscoped enum, so the calls use red, green, or blue without Color::. printColor chooses a branch by the enumerator value.

Hint 2

Add a Color variable initialized with blue and pass it to printColor. Do not use an arbitrary integer as though it were automatically a Color.

Worked solution

A new Color variable is initialized to blue and passed to printColor. It selects the blue branch and prints 2, after the original green call prints 1.

#include <iostream>

enum Color
{
    red,
    green,
    blue
};

void printColor(Color c)
{
    if (c == red)
        std::cout << 0 << '\n';
    else if (c == green)
        std::cout << 1 << '\n';
    else if (c == blue)
        std::cout << 2 << '\n';
}

int main()
{
    printColor(green);

    Color next{blue};
    printColor(next);
    return 0;
}

Example output

1
2

0 comments

No comments yet. Be the first.

Add a comment

About CppLearn

CppLearn is an interactive, free reference for modern C++. In each lesson, you'll find out how the language works, rather than just lines of code that you can copy and paste. We cover concepts starting from beginner lessons on fundamentals and proceed to templates, move semantics, smart pointers, and areas that usually trap or scare C++ learners.