home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.std.c++
- Path: sparky!uunet!mcsun!sunic!lth.se!newsuser
- From: dag@control.lth.se (Dag Bruck)
- Subject: Re: Expanding enumerators in inheriting classes
- Message-ID: <1992Aug17.062809.24177@lth.se>
- Keywords: inheritance, enumerator
- Sender: newsuser@lth.se (LTH network news server)
- Organization: Department of Automatic Control, Lund, Sweden
- References: <1992Aug10.200814.12809@ntmtv> <1992Aug11.133926.28840@actrix.gen.nz> <1992Aug11.190816.8623@inmet.camb.inmet.com> <1992Aug12.192200.6873@ntmtv> <1992Aug14.193046.6808@lth.se>
- Date: Mon, 17 Aug 1992 06:28:09 GMT
- Lines: 132
-
- 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;
- }
-