Quick summary ↬ Enumerations are always fun to use in C++ programs. C++ core guidelines define eight different rules to define the enumerations. And also, C++11 introduced the scoped enumerations also called as class enumerations. Scoped enums also have few advantages over plain enums which are also covered in this article.
Plain Enum
An enumeration is a user-defined data type that consists of integral constants. To define an enumeration, the keyword enum is used. The below example is a plain enum.
|
|
In the above example, every attribute declared inside the plain enum are values of type enum. If we haven’t assigned the integer value to all the values declared inside the enum then the compiler will assign one starting from zero.
By default, cpp is 0,algorithms is 1 etc. We can also change the default values by assigning one as shown below:
|
|
The above enum can be called by using the below statement,
|
|
enum is used mostly for declaring flags. Using enum is less expensive because it just needs int (4 bytes) to store the values by default.
We can also declare the return type of the enum as shown in the below example,
|
|
By default, enum returns integer values. In the above example, we declare that the enum courses returns 32-bit integer.
Declare multiple values with the same name inside the enum
|
|
In the above example, we have declared cpp twice. This results in the compile time error as shown below,
|
|
Why enum classes?
enum classes were introduced in C++11 and it addresses three benefits compared to the plain enum. Class enum is also called as the scoped enum or new enum or strong enum.
From Bjarne Stroustrup’s C++11 FAQ:
- conventional enums implicitly convert to int, causing errors when someone does not want an enumeration to act as an integer.
- conventional enums export their enumerators to the surrounding scope, causing name clashes.
- the underlying type of an enum cannot be specified, causing confusion, compatibility problems, and makes forward declaration possible.
The new enums are called the class enums because they combine aspects of traditional enumerations (named values) with aspects of classes (scoped members and absence of conversions).
conventional enums implicitly convert to int, causing errors when someone does not want an enumeration to act as an integer.
|
|
conventional enums export their enumerators to the surrounding scope, causing name clashes.
|
|
The underlying type of an enum cannot be specified, causing confusion, compatibility problems, and makes forward declaration impossible.
|
|
|
|
|
|
Interesting way to use enum classes with #define, #undef, #include
In the below program, I have mentioned an interesting way to declare all the enum values in a separate file and then include that file in the enum class as shown below:
|
|
Code in the main1.h file is shown below:
|
|
In the above code, we use #ifdef directive to define the values to be added in the enum class. If the DB_OBJECT_TYPE_ENUM is defined in the enum then all the values declared inside the #ifdef are included. In the above enum, we declared an array kind of enum values. It’s always needed to declare a #define macro to define the array structure so the enum class can understand that the nature of the values declared in the enum class.
C++ guidelines to declare enum and enum class
C++ core guidelines define the below guidelines to declare the enum and enum classes.
- Prefer enumerations over macros.
- Use enumerations to represent sets of related named constants.
- Prefer enum classes over plain enums.
- Define operations on enumerations for safe and simple use.
- Don’t use ALL_CAPS for enumerators.
- Avoid unnamed enumerations.
- Specify the underlying type of enumerations only when necessary.
- Specify enumerator values only when necessary.
Conclusion
It’s always better to use plain enum instead of macros. But, class enums are always better compared to plain enums and macros.