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