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?