Typesafe Enumerations

C++0x has a lot of great new features included in it. However, the “flashier” features like lambda functions have the tendency to overshadow other features. One of those features which I am guessing will be overshadowed is the ability to create truly type safe enumerations in C++.

If you’ve used C for any length of time, you’ll eventually come across the enumeration. It’s a way for you to define a logical group of named constants with a unique type. For instance:

enum Foo {
  kBar,		// Defaults to 0
  kBaz = 100,
  kFrobble	// Defaults to 101
};

This goes a long ways towards improving the readability of your code. Instead of using magic numbers everywhere, you can give hints to the programmer as to what values are acceptable for a given identifier. However, at the end of the day, enumeration values are just integers to the compiler, and the constant names are exported out of the scope of the enumeration itself. This means you can convert to and from int almost with impunity and can run into some gnarly naming conflicts.

Old-style enumerations:

enum Foo {
  kBar,
  kBaz = 100,
  kFrobble
};

enum Bar {
  kDazzle
};

enum Foo f = 12;		// Not legal, thank god
int i = kBar;			// Legal
enum Foo f2 = Foo::kBar;	// Illegal in C++98, legal in C++0x
enum Foo f3 = (enum Foo)12;	// Legal, even though it's nonsense
if (kDazzle == kBar)		// Legal, and equal!

Now, with C++0x, there are strongly typed enumerations a la the “enum class” type declaration. This combines all of the type safety and scoping rules of class declarations with the concept of enumerations.

New-style enumerations:

enum class Frobble {
  kQuux,
  kBlah
};

Frobble f = kBlah;		// Error, kBlah is not in scope
Frobble f2 = Frobble::kBlah;	// Ok
int i = Frobble::kBlah;		// Error, no conversion from Frobble to int
Frobble f3 = (Frobble)12;	// Error, no conversion from int to Frobble
if (Frobble::kBar == kDazzle)	// Error, cannot compare Frobble to int

There’s another extra benefit to using the class declaration type for enumerations — you can specify an exact type via the usual inheritance mechanism:

enum class Frobble : unsigned char {
  kQuux,
  kBlah
};

sizeof( Frobble ) == 1, regardless of compiler. If you do not specify the type explicitly, then it defaults to int. This solves a major problem when trying to write portable code. For instance, you can now write a C++ library that uses strongly typed enumerations and not have to worry that another compiler may pick a different size for the enumeration type.

Unfortunately, as of this writing, many mainstream compilers do not have support for this language feature. Visual Studio 2010 does not support it, nor does the version of Clang or GCC that comes with XCode. Hopefully support for this great language improvement will be rolled out shortly.

tl;dr: enum class provides a better mechanism for enumerations in C++0x. The enumerations no longer pollute the global namespace, have a definitive size, and are strongly-typed.

This entry was posted in C/C++ and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *