Enum vs Strongly typed enum

C++C++11Enums

C++ Problem Overview


I am a beginner in C++ programming.

Today I come across a new topic: strongly typed enum. I've researched it a bit but till now I am unable to find out why do we need this and what is the use of the same?

For example if we have:

enum xyz{a, b, c};
/*a = 0, b = 1, c = 2, (Typical C format)*/

Why do we need to write:

enum class xyz{a, b, c};

What are we trying to do here? My most important doubt is how to use it. Could you provide a small example, which will make me understand.

C++ Solutions


Solution 1 - C++

OK, first example: old-style enums do not have their own scope:

enum Animals {Bear, Cat, Chicken};
enum Birds {Eagle, Duck, Chicken}; // error! Chicken has already been declared!

enum class Fruits { Apple, Pear, Orange };
enum class Colours { Blue, White, Orange }; // no problem!

Second, they implicitly convert to integral types, which can lead to strange behaviour:

bool b = Bear && Duck; // what?

Finally, you can specify the underlying integral type of C++11 enums:

enum class Foo : char { A, B, C};

Previously, the underlying type was not specified, which could cause compatibility problems between platforms. Edit It has been pointed out in comments that you can also specify the underlying integral type of an "old style" enum in C++11.

Solution 2 - C++

There's a good article about enums at this IBM page, it's very detailed and well-written. Here are some important points in a nutshell:

The scoped enums solve most of the limitations incurred by regular enums: complete type safety, well-defined underlying type, scope issues, and forward declaration.

  • You get type safety by disallowing all implicit conversions of scoped enums to other types.

  • You get a new scope, and the enum is not anymore in the enclosing scope, saving itself from name conflicts.

  • Scoped enums gives you the ability to specify the underlying type of the enumeration, and for scoped enums, it defaults to int if you choose not to specify it.

  • Any enum with a fixed underlying type can be forward declared.

Solution 3 - C++

Values of enum class is really of type enum class, not underlying_type as for C-enums.

enum xyz { a, b, c};
enum class xyz_c { d, f, e };

void f(xyz x)
{
}

void f_c(xyz_c x)
{
}

// OK.
f(0);
// OK for C++03 and C++11.
f(a);
// OK with C++11.
f(xyz::a);
// ERROR.
f_c(0);
// OK.
f_c(xyz_c::d);

Solution 4 - C++

The enum classes ("new enums", "strong enums") address three problems with traditional C++ enumerations:

  1. conventional enums implicitly convert to int, causing errors when someone does not want an enumeration to act as an integer.
  2. conventional enums export their enumerators to the surrounding scope, causing name clashes.
  3. The underlying type of an enum cannot be specified, causing confusion, compatibility problems, and makes forward declaration impossible.

enum class ("strong enums") are strongly typed and scoped:

enum Alert { green, yellow, orange, red }; // traditional enum

enum class Color { red, blue };   // scoped and strongly typed enum
                                  // no export of enumerator names into enclosing scope
                                  // no implicit conversion to int
enum class TrafficLight { red, yellow, green };

Alert a = 7;              // error (as ever in C++)
Color c = 7;              // error: no int->Color conversion

int a2 = red;             // ok: Alert->int conversion
int a3 = Alert::red;      // error in C++98; ok in C++11
int a4 = blue;            // error: blue not in scope
int a5 = Color::blue;     // error: not Color->int conversion

Color a6 = Color::blue;   // ok

As shown, traditional enums work as usual, but you can now optionally qualify with the enum's name.

The new enums are "enum class" because they combine aspects of traditional enumerations (names values) with aspects of classes (scoped members and absence of conversions).

Being able to specify the underlying type allow simpler interoperability and guaranteed sizes of enumerations:

enum class Color : char { red, blue };	// compact representation

enum class TrafficLight { red, yellow, green };  // by default, the underlying type is int

enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U };   // how big is an E?
                                                 // (whatever the old rules say;
                                                 // i.e. "implementation defined")

enum EE : unsigned long { EE1 = 1, EE2 = 2, EEbig = 0xFFFFFFF0U };   // now we can be specific

It also enables forward declaration of enums:

enum class Color_code : char;     // (forward) declaration
void foobar(Color_code* p);       // use of forward declaration
// ...
enum class Color_code : char { red, yellow, green, blue }; // definition

The underlying type must be one of the signed or unsigned integer types; the default is int.

In the standard library, enum classes are used for:

  1. Mapping systems specific error codes: In <system_error>: enum class errc;
  2. Pointer safety indicators: In <memory>: enum class pointer_safety { relaxed, preferred, strict };
  3. I/O stream errors: In <iosfwd>: enum class io_errc { stream = 1 };
  4. Asynchronous communications error handling: In <future>: enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };

Several of these have operators, such as == defined.

Solution 5 - C++

Enum Scope

Enumerations export their enumerators to the surrounding scope. This has two drawbacks. First, it can lead to name clashes, if two enumerators in different enums declared in the same scope have the same name; second, it's not possible to use an enumerator with a fully qualified name, including the enum name.

enum ESet {a0, a, a1, b1, c3};
enum EAlpha{a, b, c}

select = ESet::a; // error
select = a;       // is ambigious

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRasmi Ranjan NayakView Question on Stackoverflow
Solution 1 - C++juanchopanzaView Answer on Stackoverflow
Solution 2 - C++SingerOfTheFallView Answer on Stackoverflow
Solution 3 - C++ForEveRView Answer on Stackoverflow
Solution 4 - C++JnanaView Answer on Stackoverflow
Solution 5 - C++RamView Answer on Stackoverflow