A new C++0x feature called forward enum declarations allows you to declare an enumeration without providing its enumerators list. Learn how using it can avert long compilation times and ODR violations.

by Danny Kalev

Aug 13, 2009

Page 2 of 3

The Repeated Enumerators List Problem

In many C++ projects, enum types that contain hundreds of enumerators are quite common. Often, these enum types are machine-generated and updated frequently. Examples of such huge enum types include a list of international airports, a list of locales supported by the application, and so on.

The problem is that whenever you update such an enum, every translation unit that references it must be compiled as well—even if the code that references the enum hasn't changed. Consider the list of airports as an example:

Seemingly, the following piece of code doesn't depend on the list of Airports' enumerators, as adding a new enumerator, changing an existing enumerator, or deleting one doesn't affect Airports' enum base (which is int):

Theoretically, the compiler can process this code without needing a complete definition of Airports, but that isn't the case. C++03 requires the presence of the entire list of enumerators to determine the underlying type of Airports. This leads to a longer compilation time and increases the risk of ODR(One Definition Rule) violations.

Scoped Enums and Enum Bases

Before diving deeper into forward declaration of enum types, you need to understand two key concepts: scoped enum types and enum bases. A scoped enum is one that is declared with the class keyword, as opposed to a traditional enum, which is unscoped.

Among other things, scoped and unscoped enums differ with respect to enumerator qualification:

As previously stated, an enum base is the underlying integral type of the enumeration. Recall that the compiler represents every enum type as an unspecified integral type that is large enough to hold every enumerator value. For scoped enums, the default base type is int. You can override it by specifying a different enum base explicitly, like this: