On Friday, 7 September 2018 at 18:18:50 UTC, Neia Neutuladh wrote:
On Friday, 7 September 2018 at 03:04:19 UTC, Josphe Brigmo wrote:
We are talking about two different things that are related:

A variant holds a set of objects. Using VariantClass limits the types to a subset and allows for inherited types to be added.

Algebraic!SomeInterface should allow anything that inherits from that interface (possibly with an explicit cast).

It doesn't.

import std.stdio, std.variant;

class A
{
}
class B : A { }

void main()
{
    B b;
    Algebraic!A a;
    a = b;

}

"Cannot store a B in a VariantN!(8LU, A). Valid types are (A)"


Why this is better is because it allows objects that may not have been inherited from some interface in the design(pre-existing).

OOP is better when you don't trust people to implement types correctly and you want them to get errors at the proper location when they get it wrong.

Structural typing is better when you don't trust people to implement types correctly and you want to make things easier on yourself when they don't.

They're both useful. Most of the time, you're dealing with your own types. Sometimes, you need a type you don't control to implement an interface.

the default way of making structural typing work in D is with templates. You can also auto-generate a wrapper type.

Cool, I will check it out. It seems it would allow DuckingVariant to be created.

It would allow you to make a wrapper type that works with a wide range of types. It's probably worse on average than writing a template to create a wrapper class that implements the interface you need.

I mean, the wrapper is pretty much (untested):

class Wrapper(Interface, Wrapped): Interface
{
  Wrapped wrapped;
  static foreach (member; __traits(allMembers, Interface))
  {
static foreach (overload; __traits(getOverloads, Interface, member))
    {
mixin(`ReturnType!Overload ` ~ method ~ `(Parameters!overload params)`
      {
        return wrapped.` ~ method ~ `(params);
      }`);
    }
  }
}

And now you don't need a VariantClass!SomeInterface, just SomeInterface.

One of the problems with the above is that it doesn't allow different 'Wrapped' to equate to the same type:

Wrapper!(I, A) != Wrapper!(I, B)

Although, by construction, they implement I

e.g., one couldn't make a variable

Wrapped!(I, A) a;

and put a Wrapped!(I,B) in it because D will think they are different types simply because the parameters are different.

I guess one needs to return a WrappedBase!I type that is common to all and does some magic to trick the compiler.




Although, maybe

Wrapped!(I, Object) a;

will allow this to work?



Reply via email to