Variant is just a class
Josphe Brigmo
JospheBrigmo at gmail.com
Fri Sep 7 23:37:05 UTC 2018
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?
More information about the Digitalmars-d
mailing list