C++ Enumeration Declarations

An enumeration is a user-defined type consisting of a set of named constants called enumerators.

For information on CLR enums, see enum class.

enum [tag] [: type] {enum-list} [declarator];   // for definition of enumerated type
enum tag declarator;   // for declaration of variable of type tag

Parameters

  • tag
    The type name given to the enumeration.

  • type
    The underlying type of the enumeration identifiers. See Remarks.

  • enum-list
    List of the enumerators contained by the enumeration.

  • declarator
    Declarator list specifying the names of the enumeration. See Overview of Declarators for more information.

Remarks

By default, the first enumerator has a value of 0, and each successive enumerator is one larger than the value of the previous one, unless you explicitly specify a value for a particular enumerator. Enumerators needn't have unique values within an enumeration. The name of each enumerator is treated as a constant and must be unique within the scope where the enum is defined. An enumerator can be promoted to an integer value. However, converting an integer to an enumerator requires an explicit cast, and the results are not defined if the integer value is outside the range of the defined enumeration.

type is the underlying type of the identifiers. This can be any scalar type, such as signed or unsigned versions of int, short, or long. bool or char is also allowed.

Enumerated types are valuable when an object can assume a known and reasonably limited set of values. Consider the example of the suits from a deck of cards:

// enumeration_declarations.cpp
// compile with: /c
class Card {
public:
   enum Suit {
      Diamonds,
      Hearts,
      Clubs,
      Spades
   };

   // Declare two constructors: a default constructor,
   //  and a constructor that sets the cardinal and
   //  suit value of the new card.
   Card();
   Card( int CardInit, Suit SuitInit );

   // Get and Set functions.
   int   GetCardinal();          // Get cardinal value of card.
   int   SetCardinal();          // Set cardinal value of card.
   Suit  GetSuit();              // Get suit of card.
   void  SetSuit(Suit new_suit); // Set suit of card.
   char *NameOf();               // Get string representation of card.

private:
   Suit  suit;
   int   cardinalValue;
};

// Define a postfix increment operator for Suit.
inline Card::Suit operator++( Card::Suit &rs, int ) {
   return rs = (Card::Suit)(rs + 1);
}

The preceding example defines a class, Card, that contains a nested enumerated type, Suit. To create a pack of cards in a program, use code such as:

Card *Deck[52];
int   j = 0;

for( Card::Suit curSuit = Card::Diamonds ; curSuit <= Card::Spades ; curSuit++ )
   for( int i = 1; i <= 13; ++i )
      Deck[j++] = new Card( i, curSuit );

In the preceding example, the type Suit is nested; therefore, the class name (Card) must be used explicitly in public references. In member functions, however, the class name can be omitted.

In the first segment of code, the postfix increment operator for Card::Suit is defined. Without a user-defined increment operator, curSuit could not be incremented. For more information about user-defined operators, see Overloaded Operators.

Consider the code for the NameOf member function (a better implementation is presented later):

#define SIZE_OF_CARD_NAMES 20
char* Card::NameOf() {   // Get the name of a card.
   static char szName[SIZE_OF_CARD_NAMES];
   static char *Numbers[] = { 
      "1", "2", "3", "4", "5", "6", "7", "8", "9",
      "10", "Jack", "Queen", "King"
   };
   static char *Suits[] = {
      "Diamonds", "Hearts", "Clubs", "Spades" 
   };

   if( GetCardinal() < 13)
      strcpy_s( szName, SIZE_OF_CARD_NAMES, Numbers[GetCardinal()] );

   strcat_s( szName, SIZE_OF_CARD_NAMES, " of " );

   switch( GetSuit() ) {
      // Diamonds, Hearts, Clubs, and Spades do not need explicit
      //  class qualifier.
      case Diamonds:
         strcat_s( szName, SIZE_OF_CARD_NAMES , "Diamonds" );
      break;
      case Hearts:
         strcat_s( szName, SIZE_OF_CARD_NAMES , "Hearts" );
      break;
      case Clubs:
         strcat_s( szName, SIZE_OF_CARD_NAMES , "Clubs" );
      break;
      case Spades:
         strcat_s( szName, SIZE_OF_CARD_NAMES , "Spades" );
      break;
   }
   return szName;
}

An enumerated type is an integral type. The identifiers introduced with the enum declaration can be used wherever constants appear. Normally, the first identifier's value is 0 (Diamonds, in the preceding example), and the values increase by one for each succeeding identifier. Therefore, the value of Spades is 3.

Any enumerator in the list, including the first one, can be initialized to a value other than its default value. Suppose the declaration of Suit had been the following:

enum Suit {
   Diamonds = 5,
   Hearts,
   Clubs = 4,
   Spades
};

Then the values of Diamonds, Hearts, Clubs, and Spades would have been 5, 6, 4, and 5, respectively. Note that 5 is used more than once.

The default values for these enumerators simplify implementation of the NameOf function:

#define SIZE_OF_CARD_NAMES 20
char* Card::NameOf() {   // Get the name of a card. 
   static char szName[SIZE_OF_CARD_NAMES];
   static char *Numbers[] = {
      "1", "2", "3", "4", "5", "6", "7", "8", "9",
      "10", "Jack", "Queen", "King"
   };
   static char *Suits[] = {
      "Diamonds", "Hearts", "Clubs", "Spades"
   };

   if( GetCardinal() < 13)
      strcpy_s( szName, SIZE_OF_CARD_NAMES, Numbers[GetCardinal()] );

   strcat_s( szName, SIZE_OF_CARD_NAMES, " of " );
   strcat_s( szName, SIZE_OF_CARD_NAMES, Suits[GetSuit()] );
   return szName;
}

The accessor function GetSuit returns type Suit, an enumerated type. Because enumerated types are integral types, they can be used as arguments to the array subscript operator. (For more information, see Subscript Operator.)

In C, the enum keyword is required to declare a variable of type enumeration. In C++, the enum keyword can be omitted. For example, given the Days enumeration from the code below:

Days tomorrow;          // Legal in C++ only

Example

// enumeration_declarations3.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

enum Days {             // Declare enum type Days
   saturday,            // saturday = 0 by default
   sunday = 0,          // sunday = 0 as well
   monday,              // monday = 1
   tuesday,             // tuesday = 2
   wednesday,           // etc.
   thursday,
   friday
};

int main() {
   enum Days today = sunday;
   switch (today) {
      case 1:
         cout << "It's Monday" << endl;
         break;
      default: 
         cout << "Not Monday" << endl;
   }
}

Not Monday

See Also

Concepts

C Enumeration Declarations

C++ Keywords

Enumerator Names

Definition of Enumerator Constants

Conversions and Enumerated Types