From: dag@control.lth.se (Dag Bruck)
Subject: Re: Expanding enumerators in inheriting classes
Keywords: inheritance, enumerator
Organization: Department of Automatic Control, Lund, Sweden
Date: Mon, 17 Aug 1992 06:28:09 GMT

In an earlier life I seriously doubted that enumerations could be
emulated with some other language elements.  That is of course a good
reason to try to do it anyway.

Here is some code that uses templates to do something that is similar
in spirit to built-in enumerations.  I have deliberately thrown out
several safety measures in these classes to give the compiler a chance
to produce code with reasonable efficiency.

I have managed to realize some important properties of built-in
enumerations:

	1.  Typed symbolic values
	2.  Overloading of operators
	3.  Similar syntax of usage (not of declaration)

As far as I can tell, there are a few fundamental differences between
the template enumeration and the built-in enumeration that we cannot
(or want to) get around:

	1.  Template enumerators are not compile-time constants
	2.  Template enumerators cannot be used as case labels
	3.  There seems to be no good way to restrict the set
	    of enumerators that belong to an enumeration

The last issue is probably worth a few words.  Template enumerators
can be created and destroyed dynamically, for example as variables
local to a function. In this version there is no way to prevent the
bit-pattern of a destroyed enumerator from floating around the
program; with built-in enumerators you at least have to use an
explicit type cast to create illegal enumerators.

The other side of this problem is that the person who defines a
template enumeration cannot assume a fixed value domain; the
application may add new enumerators to the original set.

There are also some issues regarding efficiency in a broad sense:

	1.  Template enumerators are more awkward to declare and
	    the compiler must allocate storage for them
	2.  The implementation is much less efficient, at least
	    on my system
	3.  The user must learn a class library in addition to the
	    built-in feature

Finally, my compiler will not allow template class specialization if
the member function is defined as inline.  I assume that this is an
implementation restriction, and not in the language.

An alternative approach is to toss out class Enumerator and create
class Enumeration parameterized with a built-in enumeration.  This
approach allows operator overloading of variables of class
Enumeration, but neither overloading of the enumerators nor a dynamic
set of enumerators.

			-- Dag

Code follows:

// An attempt to emulate enums with template classes.  This is the really
// lean version without any checking at all.
//
// Author: Dag Bruck, Department of Automatic Control, Lund Institute of
// Technology, Box 118, S-221 00 Lund, Sweden.  E-mail: dag@control.lth.se

// Declaration of class Enumerator

template <class E>
class Enumerator {
public:
  Enumerator() : val(++highest_value) {}
  Enumerator(int x) : val(x) { highest_value = val; }
  operator int () const { return val; }
  
private:
  int val;
  static int highest_value;
};

// Declaration of class Enumeration

template <class E>
class Enumeration {
public:
  Enumeration() : val(0) {}
  Enumeration(const Enumerator<E>& x) : val(x) {}
  Enumeration<E>& operator = (const Enumeration<E>& e)
    { val=e.val; return *this; }
  Enumeration<E>& operator |= (const Enumeration<E> e);
//  { val |= e.val; return *this; }  /* Because of compiler restriction? */
  operator int () const { return val; }

private:
  int val;
};
 
template <class E>
int Enumerator<E>::highest_value = -1;

template <class E>
inline Enumeration<E> operator | (const Enumeration<E> e1,
                                  const Enumeration<E> e2)
{
  Enumeration<E> r(e1);
  r |= e2;
  return r;
}

// Test of class Enumeration
//
// - we overload the meaning operator |= to get the desired behaviour
//   for OFAscore

struct OFAscore {};

Enumerator<OFAscore> severe, bad, marginal, fair, good, excellent;
			/* there is another one, but I forgot the name */

inline Enumeration<OFAscore>&
Enumeration<OFAscore>::operator |= (const Enumeration<OFAscore> e)
{
  if (e.val < val) val = e.val;
  return *this;
}

void main()
{
  Enumeration<OFAscore> left_hip, right_hip, total_score;
  left_hip = fair;
  right_hip = good;
  total_score = left_hip | right_hip;
}
Newsgroups: comp.std.c++