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
Test_Enum_String.h #include <string> #include "Tmpl_Enum.h" class Test_Enum_String: public Tmpl_Enum<std::string, Test_Enum_String> { private: explicit Test_Enum_String(const std::string& Value): Tmpl_Enum<std::string, Test_Enum_String>(Value) { } public: 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; }; Test_Enum_String.cpp #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"); Main.cpp #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 "; else 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 ) { Cur_Elem++; 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; Validate_Str_Elem("Alpha"); Validate_Str_Elem("Gamma"); Validate_Str_Elem("Beta"); Validate_Str_Elem("BetA"); 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; } Output: 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.
Conclusion
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.
Bibliography
[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 [email protected].