Channels ▼

When enum Just Isn't Enough: Enumeration Classes for C++

Listing 6 gives a sample testing program together with its output. The generalization is fairly straightforward: You must add another template parameter for the underlying type, which I've called TValue. To avoid copy inefficiencies, TValue is always passed by reference to const and likewise the predicate stores a const TValue&.

Listing 6


#include <string>
#include "Tmpl_Enum.h"

class Test_Enum_String:
  public Tmpl_Enum<std::string, Test_Enum_String> {


  explicit Test_Enum_String(const std::string& Value):
    Tmpl_Enum<std::string, Test_Enum_String>(Value) { }


  static const Test_Enum_String enum_Alpha;
  static const Test_Enum_String enum_Beta;
  static const Test_Enum_String enum_Delta;
  static const Test_Enum_String enum_Epsilon;
  static const Test_Enum_String enum_Omega;


#include "Test_Enum_String.h"
Tmpl_Enum<std::string, Test_Enum_String>::instances_list 
Tmpl_Enum<std::string, Test_Enum_String>::s_instances;

const Test_Enum_String Test_Enum_String::enum_Alpha("Alpha");
const Test_Enum_String Test_Enum_String::enum_Beta("Beta");
const Test_Enum_String Test_Enum_String::enum_Delta("Delta");
const Test_Enum_String Test_Enum_String::enum_Epsilon("Epsilon");
const Test_Enum_String Test_Enum_String::enum_Omega("Omega");


#include "Test_Enum_String.h"
void Validate_Str_Elem(const std::string& theString)
  using std::cout;
  using std::endl;
  cout << theString;
  if ( Test_Enum_String::Is_Valid_Value(theString) )
    cout << " is ";
    cout << " isn't ";
  cout << "a valid value for Test_Enum_String." << endl;

int main()
  using std::cout;
  using std::endl;
  int Cur_Elem = 0;
  for ( Test_Enum_String::const_iterator
        i = Test_Enum_String::begin();
        i != Test_Enum_String::end(); ++i )
    cout << "Test_Enum_String element #" << Cur_Elem << " value = " << (*i)->Get_Value() << endl;

  cout << "Total #elements = " << Test_Enum_String::size() << endl;

  cout << "Min enum value = " << Test_Enum_String::Min() << endl;
  cout << "Max enum value = " << Test_Enum_String::Max() << endl;


  Test_Enum_String E(Test_Enum_String::enum_Alpha);
  cout << "Value of E = " << E.Get_Value() << endl;

  E = Test_Enum_String::enum_Omega;
  cout << "Value of E = " << E.Get_Value() << endl;
  return 0;


Test_Enum_String element #1 value = Alpha
Test_Enum_String element #2 value = Beta
Test_Enum_String element #3 value = Delta
Test_Enum_String element #4 value = Epsilon
Test_Enum_String element #5 value = Omega
Total #elements = 5
Min enum value = Alpha

Max enum value = Omega
Alpha is a valid value for Test_Enum_String.
Gamma isn't a valid value for Test_Enum_String.
Beta is a valid value for Test_Enum_String.
BetA isn't a valid value for Test_Enum_String.
Value of E = Alpha
Value of E = Omega

If the underlying type does not have an operator< (or if this operator doesn't do what you want), you can still use an enumeration class, but you will have to generalize still further, with a third template parameter, this one a comparison object to pass to the Enum_Ptr_Less object. The details are left as an exercise for the reader.


Enumeration classes enable the encapsulation of collections of related constants. They allow programmatic access to the minimum and maximum values of the collection as well as straightforward iteration and membership tests. In their simpler form, they can be viewed as an improved form of enum. By templating them on their underlying enumerated type, they can be applied to collections of constants of any ordered type.


[1] Bjarne Stroustrup. The C++ Programming Language, 3d Edition, (Addison-Wesley, 2000), p. 265.

[2] Scott Meyers. Effective STL (Addison-Wesley, 2001), Item 20, p. 88.

Download the Code


Yves Meynard has a Ph.D. in Computer Science (Operational Research) from the Université de Montréal. He holds the post of Software Analyst at SNC Lavalin Energy Control Systems. His areas of interest include optimization heuristics and code refactoring. He may be reached at

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.