Variant is just a class

Neia Neutuladh neia at ikeran.org
Thu Sep 6 20:25:18 UTC 2018


On Thursday, 6 September 2018 at 10:18:43 UTC, Josphe Brigmo 
wrote:
>
> Variants can hold an arbitrary set of types.
>
> I imagine that it is effectively just a type id and an object 
> pointer!?

It's a typeid and a static array large enough to hold any basic 
builtin type: the now-deprecated creal, a dynamic array, or a 
delegate.

If you make a Variant from an object, it stores that object 
reference. The object reference is just a pointer, yes.

If you make a Variant from a 256-byte struct, it copies that 
struct onto the heap and stores a pointer.

If you make a Variant from a 6-byte struct, then it stores that 
struct and does no heap allocations.

> If so, then it really is just a special type of a class class.

It's similar to a java.lang.Object with explicit boxing, but 
without the need to create a new wrapper class for each value 
type.

> It seems that variant and oop are essentially the same thing, 
> more or less, as whatever can be done in one can effectively be 
> done in the other, except, of course, that the class version 
> has compile time type information associated with it, which 
> sort of restricts variant to a subset of all types!?!

Object-oriented programming includes inheritance and member 
function overloading. Variant doesn't; it's just about storage.

If you're working with classes, you'd be better off using a base 
class or interface instead of Variant for fields that can only 
hold objects of those types.

> But variant can reduce the code complexity if one restricts 
> it's inputs to a specific class of types:

Yes, for which you can use std.variant.Algebraic. For instance, 
Algebraic!(int, long, float) will accept ints, longs, and floats, 
but nothing else.

> Then VariantClass will prevent any arbitrary type from being 
> assigned to the variant, effectively allow inheritance to be 
> used(in the sense that it will prevent any type from being used 
> at compile time, like inheritance):
>
> VariantClass!X v; // only T : X's are allowed.

That's equivalent to `X v;` except with a wrapper around it.

> Matching then is dispatch. We could further extend VariantClass 
> to return specific classes for each type that dispatch to match 
> and vice versa.

I think you're saying that this sort of Algebraic could expose 
any methods and fields common to all its types?

> Can D project interfaces like this?
>
> interface I
> {
>    int foo(int);
> }
>
> I i = project!I(o);

You can write code to make that work. It would create a wrapper 
class that implements the requested interface, and that wrapper 
would just forward everything to the wrapped value.

It would be a lot easier just to have the type implement the 
interface itself, if that's possible.

> Seems though this cannot be used at runtime though since 
> function signatures are not transported in the binary? If they 
> are, then maybe it would work and would reduce the overhead of 
> oop as one could just project types to other types that overlap.

You can use the witchcraft library on dub to perform runtime 
introspection, but there would be a performance penalty.


More information about the Digitalmars-d mailing list