Use Enum with More Class!

published: July 29, 2019 — last modified: October 23, 2025

You may be familiar with enum values, but do you know about enum classes?

This great feature was introduced with C++11 to solve several problems with the regular enum declaration.

Now I will explain the enum class declaration and demonstrate its practical uses. Although the examples I provide are intended for the Arduino Uno, the concept will work with any platform and with all modern C++ compilers.

A Display Interface

Let’s assume we create modular firmware code and create an interface for the display of our device.

#pragma once

namespace Display {

enum Backlight {
  Off,
  On
};

enum StatusLed {
  Off,
  Red,
  Yellow,
  Blue,
};

void setBacklight(Backlight backlight);

void setStatusLed(StatusLed statusLed);

}

If you compile this example, it will cause a failure and display this error message:

Display.hpp:11:3: error: redeclaration of 'Off'
   Off,

The regular enum declaration will put all of its enumerators into the same namespace as the declaration itself. The list of declared identifiers will look similar to this:

Display::Backlight      [enum-name]
Display::Off            [enumerator]
Display::On             [enumerator]
Display::StatusLed      [enum-name]
Display::Off            [enumerator] <== conflict!
Display::Red            [enumerator]
Display::Yellow         [enumerator]
Display::Blue           [enumerator]
Display::setBacklight   [function]
Display::setStatusLed   [function]

Because Off is already declared by the Backlight enum, its second declaration by StatusLed causes a name conflict.

Doubtful Solutions

Prefixes

A common “solution” used to avoid name conflicts is to put a prefix in front of each name:

enum Backlight {
  BacklightOff,
  BacklightOn
};

enum StatusLed {
  StatusLedOff,
  StatusLedRed,
  StatusLedYellow,
  StatusLedBlue,
};

Occasionally, you read code that uses an underscore to separate the prefix from the name.

#pragma once

namespace Display {

enum Backlight {
  Backlight_Off,
  Backlight_On
};

enum StatusLed {
  StatusLed_Off,
  StatusLed_Red,
  StatusLed_Yellow,
  StatusLed_Blue,
};

void setBacklight(Backlight backlight);

void setStatusLed(StatusLed statusLed);

}

This underscore is introduced because the author instinctively perceives a loss of readability.

While these solutions work perfectly fine, they introduce cumbersome, repetitive code, and repetitive code always indicates a design problem.

Artificial Namespaces

Another common solution is to put the enum declaration into another namespace:

#pragma once

namespace Display {

namespace Backlight {
enum Backlight {
  Off,
  On
};
}

namespace StatusLed {
enum StatusLed {
  Off,
  Red,
  Yellow,
  Blue,
};
}

void setBacklight(Backlight::Backlight backlight);

void setStatusLed(StatusLed::StatusLed statusLed);

}

The previous example uses a namespace declaration, which creates a very ugly duplication of the name in the interface. A more creative variant is to encapsulate the enum into its own class:

#pragma once

namespace Display {

class Backlight {
public:
  enum Enum {
    Off,
    On
  };
  Backlight(Enum value) : _value(value) {}
  // operators, getters, etc.
private:
  Enum _value;  
};

class StatusLed {
public:
  enum Enum {
    Off,
    Red,
    Yellow,
    Blue,
  };
  StatusLed(Enum value) : _value(value) {}
  // operators, getters, etc.
private:
  Enum _value;  
};

void setBacklight(Backlight backlight);

void setStatusLed(StatusLed statusLed);

}

Both of these solutions allow for clear and simple use of the interface, which is an improvement over the first ones.

#include "Display.hpp"

void setup() {
  Display::setBacklight(Display::Backlight::On);
  Display::setStatusLed(Display::StatusLed::Red);
}

void loop() {
}

Using an Enum Class

Enum classes work like a regular enum declaration, but put all enumerators into a new namespace:

#pragma once

namespace Display {

enum class Backlight {
  Off,
  On
};

enum class StatusLed {
  Off,
  Red,
  Yellow,
  Blue,
};

void setBacklight(Backlight backlight);

void setStatusLed(StatusLed statusLed);

}

Let’s now look at all identifiers declared in the previous example:

Display::Backlight           [enum-name]
Display::Backlight::Off      [enumerator]
Display::Backlight::On       [enumerator]
Display::StatusLed           [enum-name]
Display::StatusLed::Off      [enumerator]
Display::StatusLed::Red      [enumerator]
Display::StatusLed::Yellow   [enumerator]
Display::StatusLed::Blue     [enumerator]
Display::setBacklight        [function]
Display::setStatusLed        [function]

The declaration of the enum is simple and the two Off enumerators are separated in their own namespaces.

Syntax

Declaring an enum class is nearly identical to a regular enum declaration. The only difference is the class keyword after enum:

enum class [enum name] {
  [enumerator 1],
  [enumerator 2],
  [enumerator 3],
  ...
};

As is true for regular enum declarations, you can set an explicit base type and provide an initialiser for each enumerator:

enum class Speed : uint8_t {
  Slow = 0x10u,
  Medium = 0x40u,
  Fast = 0xa5u,
};

Usage

Enum classes are used in the exact same way as regular enum types. The only difference is the additional namespace you must put in front of the enumerator:

#include "Display.hpp"

void setup() {
  Display::setBacklight(Display::Backlight::On);
  Display::setStatusLed(Display::StatusLed::Red);
}

void loop() {
  Display::setStatusLed(Display::StatusLed::Blue);
  delay(200);  
  Display::setStatusLed(Display::StatusLed::Yellow);
  delay(200);  
  Display::setStatusLed(Display::StatusLed::Red);
  delay(200);  
}

This can lead to repetitive code with long identifier names, which is less than ideal. You can easily solve this problem using local using declarations:

#include "Display.hpp"

void setup() {
  using namespace Display;
  setBacklight(Backlight::On);
  setStatusLed(StatusLed::Red);
}

void loop() {
  using namespace Display;
  setStatusLed(StatusLed::Blue);
  delay(200);  
  setStatusLed(StatusLed::Yellow);
  delay(200);  
  setStatusLed(StatusLed::Red);
  delay(200);  
}

Here, the using namespace declaration is only working with an actual namespace, but not with a class.

Let’s assume we created a class-based Display interface as shown in the following example:

#pragma once

class Display
{
public:
  enum class Backlight {
    Off,
    On
  };
  
  enum class StatusLed {
    Off,
    Red,
    Yellow,
    Blue,
  };
  
  void setBacklight(Backlight backlight);
  void setStatusLed(StatusLed statusLed);
};

The using namespace will not work with the Display class. Instead, we can declare new names in our namespace for the enum types:

#include "Display.hpp"

using Backlight = Display::Backlight;
using StatusLed = Display::StatusLed;

Display gDisplay;

void setup() {
  gDisplay.setBacklight(Backlight::On);
  gDisplay.setStatusLed(StatusLed::Red);
}

void loop() {
  gDisplay.setStatusLed(StatusLed::Blue);
  delay(200);  
  gDisplay.setStatusLed(StatusLed::Yellow);
  delay(200);  
  gDisplay.setStatusLed(StatusLed::Red);
  delay(200);  
}

When Should I Use Enum Classes?

You should use an enum class if the additional namespace will improve the readability of your code.

  • The enum is used on its own in an interface, as demonstrated with the in an interface, as demonstrated with the Display interface. interface.
  • The enumerator names may be confusing out of context, like , like Off and and On..
  • If you prefix each enumerator name, like , like Backlight_Off and and Backlight_On..

If you already introduced a namespace, and the enumerator names are unique and make sense, you should use a regular enum declaration.

When deciding, always consider how your interface is used. Your goal must be to make this code clear and readable.

Conclusion

Using enum classes will keep the names of enumerators simple and prevent name conflicts. The namespace in front of each enumerator associates the name with the enum type, increasing the readability of the code.

If you have questions, missed any information, or simply wish to provide feedback, simply add a comment below or ask a question on Twitter!

More Posts

How to Debug Time Critical Code using an Oscilloscope

Posted on 2014-11-13— How and Why

I often use a simple oscilloscope trick to debug time-critical code: toggle an I/O line before and after critical sections and observe interrupt timing and execution width. It’s low-effort and revealing — read on for practical steps, examples, and tips to measure and reason about your timing issues.

Read this post

Write Less Code using the "auto" Keyword

Posted on 2019-07-12— C++, Improve your Code, Learn

I walk through practical ways I use C++11's auto keyword to reduce repetitive declarations, simplify range-based for loops, lambdas and register access, and make Arduino and embedded code easier to refactor. Read the full post for examples and tips you can apply to your projects.

Read this post

Testing the TPS61092 Boost Converter

Posted on 2018-03-17— Projects

I built a small test board for the TPS61092 to evaluate thermal performance, hand‑solderability, and layout before using it in my project. The chip stayed cool under 0.5A and the OSH Park PCB looked great. Read on for measurements, the BOM, and practical soldering tips if you want to try it.

Read this post

Boards in Good Quality from SeeedStudio Fusion

Posted on 2018-02-11— Review

I tested SeeedStudio's Fusion PCB service for a new prototype and ordered five blue, 2-layer FR‑4 boards with lead‑free HASL. Delivery took about 10 days and the boards showed good quality for the price. Read on for details about ordering, solder mask, and tolerances.

Read this post

Let’s Print a Cat/Pet Feeding Device (Part 7)

Posted on 2021-04-03— 3D Printing, Projects

I walk through the sensor board I designed for the pet feeder, explaining the position sensor, four fill sensors, and why component choices (like the 100kΩ resistor) matter. I keep the design simple and practical — read the full post for schematics, measurements, and ordering details.

Read this post

Logic Gates Puzzle 100

Posted on 2021-05-04— Puzzle

I uncovered an ancient stone with a mysterious multiplexed display — five inputs and six outputs. In this puzzle I explore what the display likely represents and invite you to find the longest continuous sequence of numbers it can show. Try the interactive panel and read the full post to solve it.

Read this post