Listing 5: A generalized enumeration class

#include <functional>
#include <set>

template <class TValue, class T>
class Tmpl_Enum {

private:

 // Constructors
 explicit Tmpl_Enum(const TValue& Value);

 // Predicate for finding the corresponding instance
 struct Enum_Predicate_Corresponds:
    public std::unary_function<const Tmpl_Enum<TValue, T>*, bool> {

      Enum_Predicate_Corresponds(const TValue& Value): m_value(Value) { 
}
      bool operator()(const Tmpl_Enum<TValue, T>* E)
      { return E->Get_Value() == m_value; }

    private:
      const TValue& m_value;
 };

 // Comparison functor for the set of instances
 struct Enum_Ptr_Less:
    public std::binary_function<const Tmpl_Enum<TValue, T>*, const Tmpl_Enum<TValue, T>*, bool> {
      bool operator()(const Tmpl_Enum<TValue, T>* E_1, const Tmpl_Enum<TValue, T>* E_2)
      { return E_1->Get_Value() < E_2->Get_Value(); }
 };

public:
 // Compiler-generated copy constructor and operator= are OK.

 typedef std::set<const Tmpl_Enum<TValue, T>*, Enum_Ptr_Less> instances_list;
 typedef instances_list::const_iterator const_iterator;

 // Access to TValue value
 const TValue& Get_Value(void) const { return m_value; }
 static const TValue& Min(void) { return (*s_instances.begin())->m_value; }
 static const TValue& Max(void) { return (*s_instances.rbegin())->m_value; }
 static const Tmpl_Enum<TValue, T>* Corresponding_Enum(const TValue& Value)
 { const_iterator it = find_if(s_instances.begin(), s_instances.end(), Enum_Predicate_Corresponds(Value));
    return (it != s_instances.end()) ? *it : NULL; }
 static bool Is_Valid_Value(const TValue& Value) { return Corresponding_Enum(Value) != NULL; }

 // Number of elements
 static instances_list::size_type size(void) { return s_instances.size(); }

 // Iteration
 static const_iterator begin(void) { return s_instances.begin(); }
 static const_iterator end(void) { return s_instances.end(); }

private:
 TValue m_value;

 static instances_list s_instances;
};


template <class TValue, class T>
inline Tmpl_Enum<TValue, T>::Tmpl_Enum(const TValue& Value):
 m_value(Value)
{
 s_instances.insert(this);
}