home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #20 / NN_1992_20.iso / spool / comp / lang / cplus / 13385 < prev    next >
Encoding:
Text File  |  1992-09-08  |  5.8 KB  |  169 lines

  1. Path: sparky!uunet!elroy.jpl.nasa.gov!usc!wupost!uwm.edu!ogicse!mintaka.lcs.mit.edu!ai-lab!life.ai.mit.edu!tmb
  2. From: tmb@arolla.idiap.ch (Thomas M. Breuel)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: zero-length datatype
  5. Message-ID: <TMB.92Sep8141523@arolla.idiap.ch>
  6. Date: 8 Sep 92 18:15:23 GMT
  7. Article-I.D.: arolla.TMB.92Sep8141523
  8. References: <TMB.92Sep7171355@arolla.idiap.ch> <MCGRANT.92Sep7142456@rascals.stanford.edu>
  9. Sender: news@ai.mit.edu
  10. Reply-To: tmb@idiap.ch
  11. Distribution: comp
  12. Organization: IDIAP (Institut Dalle Molle d'Intelligence Artificielle
  13.     Perceptive)
  14. Lines: 152
  15. In-reply-to: mcgrant@rascals.stanford.edu's message of 7 Sep 92 21:24:56 GMT
  16.  
  17. In article <MCGRANT.92Sep7142456@rascals.stanford.edu> mcgrant@rascals.stanford.edu (Michael C. Grant) writes:
  18.  
  19.    In article <TMB.92Sep7171355@arolla.idiap.ch>
  20.    tmb@arolla.idiap.ch (Thomas M. Breuel) writes:
  21.  
  22.       Consider, for example, the following template class definition:
  23.  
  24.           template <class A,class B>
  25.           struct Bar {
  26.               A x;
  27.               B y;
  28.           };
  29.  
  30.  
  31.       Now, the straightforward declaration obviously fails.
  32.  
  33.           Bar<int,void> s;
  34.  
  35.    I don't find this straightforward at all. It seems to me that a
  36.    parametrized type is not properly parametrized if some of the types
  37.    may contain a 'void' entry like that.
  38.  
  39. "void" (or its equivalent) is a perfectly good type in many
  40. programming languages. It has exactly one value and does not need to
  41. be represented in the data structure at all precisely because it has
  42. only one value.
  43.  
  44.    Perhaps there should be two
  45.    different parametrized types, one that contains B and one that
  46.    doesn't, and sufficient conversion operators, if necessary, between
  47.    the two of them.
  48.  
  49. I thought C++ was about code reuse and not imposing arbitrary
  50. restrictions.
  51.  
  52. It is quite common that dictionary classes are used only for their key
  53. values, not for their corresponding data values. For the simplest
  54. example, consider "awk" arrays, where you don't even have a choice.
  55. There is nothing "unclean" or "strange" about this: you are simply not
  56. interested in associating a non-trivial value with your keys. It would
  57. be nice if the data values that you are not using didn't occupy any
  58. memory.
  59.  
  60.    It is also quite necessary. Suppose that 'void' had zero length,
  61.    and you instantiated
  62.  
  63.    Bar<void,int>s.
  64.  
  65.    Then the pointer to member A would have the same address as the pointer
  66.    to member B! That should certainly not happen, since they are two different
  67.    objects. The ARM has something quite specific to say about that.
  68.  
  69. I don't see why that is a problem. In particular, existing programs
  70. don't use the feature, and whether I use it in new programs would be
  71. up to me.
  72.  
  73.       One fix might be to allow definitions of objects of type "void", give
  74.       them zero length, and introduce a single value for objects of type
  75.       "void", denoted "void()". Of course, there would be some minor
  76.       conflicts with the "function(void)" syntax, but those could be
  77.       resolved compatibly. Alternatively, another built-in special type
  78.       could be introduced, say, called "unit", that would be available
  79.       (only) after "#include <unit.h>".
  80.  
  81.    I certainly should not have to 'include' any definition of a built-in
  82.    type.
  83.  
  84. You already have to "#include" lots of things in order to get at
  85. compiler primitives (including some built-in types in some compilers).
  86. For example, some of the definitions in "math.h", "alloca.h" and
  87. "setjmp/longjmp" are often compiler built-ins.
  88.  
  89. The reason for making such language extensions dependent on a
  90. "#include" is to reduce the potential for name conflicts with existing
  91. code. Commonly, such "#include" files contain something like the
  92. following:
  93.  
  94.     /* __builtin_alloca is recognized as a keyword by the compiler */
  95.     #define alloca(x) __builtin_alloca(x)
  96.  
  97.    I don't understand why those 4 bytes are causing you such a stink. Perhaps
  98.    you could enlighten us as to why a truly zero length data type is even
  99.    necessary?
  100.  
  101. Under the current rules,
  102.  
  103.       struct nothing {};
  104.       HashTable<int,nothing> table(1000000);
  105.  
  106. table takes up 8Mbytes (on most machines). If you could write
  107.  
  108.       HashTable<int,void> table(1000000);
  109.  
  110. table takes up 4Mbytes.
  111.  
  112.    Also, I would like to see what templated member functions that
  113.    operate on the above object would have to do to deal with the case of
  114.    a 'void' type.
  115.     
  116. Consider:
  117.  
  118.        template <class Key,class Value>
  119.        class HashTable {
  120.        public:
  121.             void add(Key key,Value value);
  122.             int is_member(Key key);
  123.             Value lookup(Key key);
  124.        };
  125.  
  126. If you instantiate this using "HashTable<int,void>", you would get
  127. the equivalent of:
  128.  
  129.        class HashTable_int_void {
  130.        public:
  131.             void add(int &key,void &value);
  132.             int key_is_member(int &key);
  133.             void lookup(int &key);
  134.        };
  135.  
  136. Now, this is a perfectly useful data type. Consider:
  137.  
  138.       Bag<int> intersect_integers(Bag<int> &a,Bag<int> &b) {
  139.               HashTable<int,void> table;
  140.           Bag<int> result;
  141.           for(int i=0;i<a.length();i++)
  142.                   table.add(a(i),void());
  143.           for(i=0;i<b.length();i++)
  144.                   if(key_is_member(table.b(i)))
  145.                       result.add(b(i));
  146.               return result;
  147.       }
  148.  
  149. Obviously, there is little reason to call the function "lookup" now,
  150. but everything would still be consistent. Consider, for example,
  151. the following code fragment:
  152.  
  153.        Value x = lookup(some_key);
  154.  
  155. This would simply turn into:
  156.  
  157.        void x = lookup(some_key);
  158.  
  159. Obviously, a "void" variable could be initialized by the return value
  160. ("void()") of a "void" function.
  161.  
  162. It's not a major thing, but I still find the current restriction
  163. pretty arbitrary (there are lots of sentences devoted in the ARM to
  164. saying "you can't do this with 'void' and you can't do that with
  165. 'void'"), and it is inconvenient. Other languages have the equivalent
  166. of the "void" value and "void" variables; why not C++?
  167.  
  168.                     Thomas.
  169.