It's a class! It's a struct! It's ... SuperStruct!

rcorre via Digitalmars-d-announce digitalmars-d-announce at puremagic.com
Sun Oct 18 12:00:10 PDT 2015


SuperStruct is a struct that acts like a class:

---
struct Square {
   float size;
   float area() { return size * size; }
}

struct Circle {
   float r;
   float area() { return r * r * PI; }
}

alias Shape = SuperStruct!(Square, Circle);

// look! polymorphism!
Shape sqr = Square(2);
Shape cir = Circle(4);
Shape[] shapes = [ sqr, cir ];

// call functions that are shared between the source types!
assert(shapes.map!(x => x.area).sum.approxEqual(2 * 2 + 4 * 4 * 
PI));
---

SuperStruct is basically a Variant that exposes the common 
members of its source
types. You can check it out here:

https://github.com/rcorre/superstruct

I'm not quite sure if this is a good idea (or if it already 
exists in some
form that I haven't seen), but it was fun to work on. There's a 
lot more info on
the README if you're curious. Let me know what you think!



If you're wondering why I even wanted to do something like this:

I had this Variant that stored either a SpriteBatch, a TextBatch, 
or a Primitive
batch. The thing is, I had a group of them that had to be sorted 
by depth. Each
one of those types _had_ a depth, but it just wasn't accessible 
through the
variant. Not a big deal, of course:

---
struct Batch {
   Algebraic!(SpriteBatch, TextBatch, PrimitiveBatch) _batch;
   auto depth() {
     return _batch.visit!(
         (SpriteBatch    b) => b.depth,
         (TextBatch      b) => b.depth,
         (PrimitiveBatch b) => b.depth);
   }
}
---

And that worked fine for a bit. Then each of them got a blender 
too:

---
   auto blender() {
     return _batch.visit!(
         (SpriteBatch    b) => b.blender,
         (TextBatch      b) => b.blender,
         (PrimitiveBatch b) => b.blender);
   }
---

Later, I thought it might be nice if a batch had a global 
transform.
You can probably guess what that looked like...

I started to think maybe Batch should be a class ... but these 
were value types,
dammit! All I wanted was a little polymorphism! Sure, theres 
std.typecons.wrap,
but that doesn't (yet) work on structs, and besides, it's really 
a class on the
inside!

Instead of (logically?) just using classes, I decided to go nuts 
with templates,
and so SuperStruct was born.



More information about the Digitalmars-d-announce mailing list