home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / std / cplus / 1085 < prev    next >
Encoding:
Text File  |  1992-08-16  |  4.7 KB  |  145 lines

  1. Newsgroups: comp.std.c++
  2. Path: sparky!uunet!mcsun!sunic!lth.se!newsuser
  3. From: dag@control.lth.se (Dag Bruck)
  4. Subject: Re: Expanding enumerators in inheriting classes
  5. Message-ID: <1992Aug17.062809.24177@lth.se>
  6. Keywords: inheritance, enumerator
  7. Sender: newsuser@lth.se (LTH network news server)
  8. Organization: Department of Automatic Control, Lund, Sweden
  9. 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>
  10. Date: Mon, 17 Aug 1992 06:28:09 GMT
  11. Lines: 132
  12.  
  13. In an earlier life I seriously doubted that enumerations could be
  14. emulated with some other language elements.  That is of course a good
  15. reason to try to do it anyway.
  16.  
  17. Here is some code that uses templates to do something that is similar
  18. in spirit to built-in enumerations.  I have deliberately thrown out
  19. several safety measures in these classes to give the compiler a chance
  20. to produce code with reasonable efficiency.
  21.  
  22. I have managed to realize some important properties of built-in
  23. enumerations:
  24.  
  25.     1.  Typed symbolic values
  26.     2.  Overloading of operators
  27.     3.  Similar syntax of usage (not of declaration)
  28.  
  29. As far as I can tell, there are a few fundamental differences between
  30. the template enumeration and the built-in enumeration that we cannot
  31. (or want to) get around:
  32.  
  33.     1.  Template enumerators are not compile-time constants
  34.     2.  Template enumerators cannot be used as case labels
  35.     3.  There seems to be no good way to restrict the set
  36.         of enumerators that belong to an enumeration
  37.  
  38. The last issue is probably worth a few words.  Template enumerators
  39. can be created and destroyed dynamically, for example as variables
  40. local to a function. In this version there is no way to prevent the
  41. bit-pattern of a destroyed enumerator from floating around the
  42. program; with built-in enumerators you at least have to use an
  43. explicit type cast to create illegal enumerators.
  44.  
  45. The other side of this problem is that the person who defines a
  46. template enumeration cannot assume a fixed value domain; the
  47. application may add new enumerators to the original set.
  48.  
  49. There are also some issues regarding efficiency in a broad sense:
  50.  
  51.     1.  Template enumerators are more awkward to declare and
  52.         the compiler must allocate storage for them
  53.     2.  The implementation is much less efficient, at least
  54.         on my system
  55.     3.  The user must learn a class library in addition to the
  56.         built-in feature
  57.  
  58. Finally, my compiler will not allow template class specialization if
  59. the member function is defined as inline.  I assume that this is an
  60. implementation restriction, and not in the language.
  61.  
  62. An alternative approach is to toss out class Enumerator and create
  63. class Enumeration parameterized with a built-in enumeration.  This
  64. approach allows operator overloading of variables of class
  65. Enumeration, but neither overloading of the enumerators nor a dynamic
  66. set of enumerators.
  67.  
  68.             -- Dag
  69.  
  70. Code follows:
  71.  
  72. // An attempt to emulate enums with template classes.  This is the really
  73. // lean version without any checking at all.
  74. //
  75. // Author: Dag Bruck, Department of Automatic Control, Lund Institute of
  76. // Technology, Box 118, S-221 00 Lund, Sweden.  E-mail: dag@control.lth.se
  77.  
  78. // Declaration of class Enumerator
  79.  
  80. template <class E>
  81. class Enumerator {
  82. public:
  83.   Enumerator() : val(++highest_value) {}
  84.   Enumerator(int x) : val(x) { highest_value = val; }
  85.   operator int () const { return val; }
  86.   
  87. private:
  88.   int val;
  89.   static int highest_value;
  90. };
  91.  
  92. // Declaration of class Enumeration
  93.  
  94. template <class E>
  95. class Enumeration {
  96. public:
  97.   Enumeration() : val(0) {}
  98.   Enumeration(const Enumerator<E>& x) : val(x) {}
  99.   Enumeration<E>& operator = (const Enumeration<E>& e)
  100.     { val=e.val; return *this; }
  101.   Enumeration<E>& operator |= (const Enumeration<E> e);
  102. //  { val |= e.val; return *this; }  /* Because of compiler restriction? */
  103.   operator int () const { return val; }
  104.  
  105. private:
  106.   int val;
  107. };
  108.  
  109. template <class E>
  110. int Enumerator<E>::highest_value = -1;
  111.  
  112. template <class E>
  113. inline Enumeration<E> operator | (const Enumeration<E> e1,
  114.                                   const Enumeration<E> e2)
  115. {
  116.   Enumeration<E> r(e1);
  117.   r |= e2;
  118.   return r;
  119. }
  120.  
  121. // Test of class Enumeration
  122. //
  123. // - we overload the meaning operator |= to get the desired behaviour
  124. //   for OFAscore
  125.  
  126. struct OFAscore {};
  127.  
  128. Enumerator<OFAscore> severe, bad, marginal, fair, good, excellent;
  129.             /* there is another one, but I forgot the name */
  130.  
  131. inline Enumeration<OFAscore>&
  132. Enumeration<OFAscore>::operator |= (const Enumeration<OFAscore> e)
  133. {
  134.   if (e.val < val) val = e.val;
  135.   return *this;
  136. }
  137.  
  138. void main()
  139. {
  140.   Enumeration<OFAscore> left_hip, right_hip, total_score;
  141.   left_hip = fair;
  142.   right_hip = good;
  143.   total_score = left_hip | right_hip;
  144. }
  145.