home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / std / cplus / 1948 < prev    next >
Encoding:
Text File  |  1993-01-01  |  3.7 KB  |  115 lines

  1. Newsgroups: comp.std.c++
  2. Path: sparky!uunet!munnari.oz.au!metro!extro.ucc.su.OZ.AU!maxtal
  3. From: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
  4. Subject: Variants
  5. Message-ID: <1993Jan1.174133.12629@ucc.su.OZ.AU>
  6. Sender: news@ucc.su.OZ.AU
  7. Nntp-Posting-Host: extro.ucc.su.oz.au
  8. Organization: MAXTAL P/L C/- University Computing Centre, Sydney
  9. Date: Fri, 1 Jan 1993 17:41:33 GMT
  10. Lines: 103
  11.  
  12. I am considering the problem of heterogenous aggregates,
  13. in which for example we have an array of pointers to objects
  14. that may be either a V1, V2 or V3 object. These objects need
  15. not share a common base, and even if they did, we do not
  16. wish to use dynamic downcasting for this purpose.
  17.  
  18. Furthermore, the classes for V1, V2 and V3 may already be
  19. closed and not available for modification, and they
  20. may or may not contain virtual functions.
  21.  
  22. The 'correct' solution is basically as follows:
  23.  
  24.     struct V {
  25.         enum {t1,t2,t3} tag;
  26.         union {
  27.             V1 * v1;
  28.             V2 * v2;
  29.             V3 * v3;
  30.         };
  31.         V(V1* x1) : tag(t1), v1(x1) {}
  32.         V(V2* x2) : tag(t2), v2(x2) {}
  33.         V(V3* x3) : tag(t3), v3(x3) {}
  34.     } v;
  35.  
  36.     switch(v.tag) {
  37.         case t1: ... v.v1 ... break; 
  38.         case t2: ... v.v2 ... break;
  39.         case t3: ... v.v3 ... break;
  40.     };
  41.  
  42. This is better than using a void* and a cast I think, because it constrains
  43. the user to accessing one of the declared types V1, V2 or V3.
  44.  
  45. However, it is clearly insecure in that the tag need not agree with the
  46. actual type pointed to, and the switch might have the same problem
  47. (to say nothing of forgetting the break).
  48.  
  49. To fix this problem I invent a secure form of the union called a variant,
  50. its not quite as above but that is the initial picture.
  51.  
  52.     variant V [V1*, V2*, V3*] v;
  53.     select(v)
  54.     {
  55.         type(V1* v1) { ... v1 ... }
  56.         type(V2* v2) { ... v2 ... }
  57.         type(V3* v3) { ... v3 ... } 
  58.     }
  59.  
  60. By not naming the union components or providing explict access to the type
  61. tag the only way to access the components is via a select statement.
  62. Provided the variant is properly initialised this is statically
  63. secure.
  64.  
  65.     The code
  66.  
  67.     v->print();
  68.  
  69. is also allowed if all the Vi have a print function, it expands to the
  70. obvious select statement without the overhead of replicated source.
  71. In general, any statement containing the name of a variant
  72. (except initialisation) 
  73. is nominally expanded into multiple statements in the obvious way.
  74. I say 'nominally' because often we can restructure things to optimise
  75. them, by expanding only up to the smallest unifying subexpression.
  76.  
  77. Variants are initialised in the obvious way, the static type of the
  78. initialiser is used to set the tag field.
  79.  
  80.     V v=V1(); // v is now a V1
  81.  
  82. The usual function overloading/matching rules can be applied
  83. in most places you expect.
  84.  
  85. ***Problem 1**** assignment causes some problems. If interpreted
  86. as user defined assignment, the type cannot be changed, if
  87. the type changes like an initialisation then user defined assignments
  88. will not perform as expected. Mm. BTW: this is the only big problem
  89. I can think of.
  90.  
  91. It is clearly implied that one can have variant functions:
  92.  
  93.     f(V) { ... }
  94.  
  95. which of course accept a variant OR any of its components.
  96.  
  97. Now to the interesting bits. Naturally one must ask,
  98. what happens if one specialises or instantiates a template
  99. function with a variant or variant object? Do we generate
  100. a single variant function or a family of ordinary functions?
  101.  
  102. The answer is .. it is implementation defined. It doesnt matter.
  103. Variants commute with templates. 
  104.  
  105. There is more ... but this will do for a start.
  106.  
  107. Comments? Any help with the assignment problem?
  108.  
  109.  
  110. -- 
  111. ;----------------------------------------------------------------------
  112.         JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
  113.     Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
  114. ;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
  115.