Struct polymorphism?

Era Scarecrow rtcvb32 at yahoo.com
Sat Oct 6 20:09:06 PDT 2012


  As I'm looking over the bottlenecks in speed and useage I'm 
finding that classes are much too bulky for the subrecords I'll 
be needing. This poses a problem. The average subrecord is 
something like 64bytes, and the data structure for the class by 
itself is over 300 (last I saw somewhere), plus the virtual table 
and declared variables. Keep in mind I'll likely be working with 
well over 400,000 entries, so memory and speed become an issue 
the larger this scales up with classes. (My tests on a 80Mb input 
file became over 500Mb and took a while to load)

  As I'm thinking about this, I wonder if I can trim that to a 
minimum. Let's consider this (posted on another forum as notes 
mostly):

[code]
enum Type { normal, FRMR, LAND }
struct SubRecord {
   Type polyMorph;

   //other data
   string generateID();
}

struct FRMR {
   SubRecord root;
   alias root this; //subtyping

   //no new data is added, only methods/behavior

   string generateID() { //overrides original subrecord's
          //generate string
          //or if i use root.generateID(), i get the original
          return "";
   }
}
struct LAND {
   SubRecord root;
   alias root this; //subtyping
}

  union {
    SubRecord subrecord;
    FRMR frmr;
    LAND land;
  }

  subrecord.generateID(); //legal
  if (subrecord.polymorph == Type.FRMR)
    frmr.generateID(); //get FRMR behavior at no cost!
  if (subrecord.polymorph == Type.LAND)
    frmr.generateID(); //get FRMR behavior at no cost!
[/code]

  Now as long as you're willing to check for individual subrecords 
(and there's only 5 or so so it isn't a huge issue), but growth 
to polymorphism quickly could escalate it to be large and 
annoying. To make it truly poly-morphic then perhaps the 
following.

[code]
  struct SubRecord {
   Type polymorph;

   string generateID() {
     if (polymorph)
           return polymorphed!(polymorph, "generateID");

     string ID;
     //generate normal SubRecord ID
     return ID;
   }

   auto polymorphed(poly, string call, Vars[] ...)() {
     string typeName; //convert somewhere in here.

     mixin("return (cast(" ~ typeName ~ ") this)." ~ call ~ "(" ~ 
Vars ~ ");");
   }
  }
[/code]

  now I'm sure the template calling is likely wrong (as poly's 
value is runtime), but re-arranging it so it separates out the 
enums at runtime and then calls static versions of them you can 
get the wanted effect.

  Now assuming you get the code above working then...

[code]
   SubRecord sr, sr2;

   sr2.Type = Type.FRMR;

   sr.generateID();
   sr2.generateID(); //FRMR version! Minimal cost!
[/code]


  Thoughts? Ideas? Does this seem feasible? Potential issues down 
the road? I'll be experimenting to see if I can indeed do this. 
If someone is already done or failed at this I wouldn't mind 
reading their attempts on it.


More information about the Digitalmars-d-learn mailing list