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.