SuperStruct

A Variant which exposes members that are common across all SubTypes.

A SuperStruct!(SubTypes...) wraps an Algebraic!(SubTypes...). It can hold a single value from any of its SubTypes.

Unlike a Variant/Algebraic, SuperStruct exposes access to 'common' members that have compatible signatures.

A member is 'common' if its name describes a public function or field on every one of SubTypes. A call signature for a given member is 'compatible' if, for an instance of any one of SubTypes, that member can be called with the provided set of arguments _and_ all such calls have a common return type.

SuperStruct ignores members beginning with "__".

struct SuperStruct (
SubTypes...
) {}

Constructors

this
this(V value)

Construct and populate with an initial value.

Examples

If all types have a matching field, it gets exposed:

struct Foo { int a; }
struct Bar { int a; }
auto foobar = SuperStruct!(Foo, Bar)(Foo(1));
foobar.a = 5;
assert(foobar.a == 5);

If all types have a matching method, all compatible overloads are exposed:

struct Foo {
  int fun(int i) { return i; }
  int fun(int a, int b) { return a + b; }
}
struct Bar {
  int fun(int i) { return i; }
  int fun(int a, int b) { return a + b; }
  int fun(int a, int b, int c) { return a + b + c; }
}

auto foobar = SuperStruct!(Foo, Bar)(Foo());
assert(foobar.fun(1)    == 1);
assert(foobar.fun(1, 2) == 3);
assert(!__traits(compiles, foobar.fun(1,2,3))); // no such overload on Foo

If a name is a field on one type and a method on another, it is exposed:

struct Foo { int a; }
struct Bar {
  private int _a;
  int a() { return _a; }
  int a(int val) { return _a = val; }
}

auto foo = SuperStruct!(Foo, Bar)(Foo());
foo.a = 5;          // sets Foo.a
assert(foo.a == 5); // gets Foo.a

auto bar = SuperStruct!(Foo, Bar)(Bar());
bar.a = 5;          // invokes Bar.a(int val)
assert(bar.a == 5); // invokes Bar.a()

Meta