This module implements a
discriminated union
type (a.k.a.
tagged union,
algebraic type).
Such types are useful
for type-uniform binary interfaces, interfacing with scripting
languages, and comfortable exploratory programming.
Synopsis
Variant a; // Must assign before use, otherwise exception ensues
// Initialize with an integer; make the type int
Variant b = 42;
assert(b.type == typeid(int));
// Peek at the value
assert(b.peek!(int) !is null && *b.peek!(int) == 42);
// Automatically convert per language rules
auto x = b.get!(real);
// Assign any other type, including other variants
a = b;
a = 3.14;
assert(a.type == typeid(double));
// Implicit conversions work just as with built-in types
assert(a < b);
// Check for convertibility
assert(!a.convertsTo!(int)); // double not convertible to int
// Strings and all other arrays are supported
a = "now I'm a string";
assert(a == "now I'm a string");
a = new int[42]; // can also assign arrays
assert(a.length == 42);
a[5] = 7;
assert(a[5] == 7);
// Can also assign class values
class Foo {}
auto foo = new Foo;
a = foo;
assert(*a.peek!(Foo) == foo); // and full type information is preserved
A Variantobject can hold a value of any type, with very few
restrictions (such as shared types and noncopyable types). Setting the value
is as immediate as assigning to the Variantobject. To read back the value of
the appropriate type T, use the get!T call. To query whether a
Variant currently holds a value of type T, use peek!T. To fetch the
exact type currently held, call type, which returns the TypeInfo of
the current value.
In addition to Variant, this module also defines the Algebraic
type constructor. Unlike Variant, Algebraic only allows a finite set of
types, which are specified in the instantiation (e.g. Algebraic!(int,
string) may only hold an int or a string).
Credits
Reviewed by Brad Roberts. Daniel Keep provided a detailed code review
prompting the following improvements: (1) better support for arrays; (2) support
for associative arrays; (3) friendlier behavior towards the garbage collector.
Algebraic data type restricted to a closed set of possible
types. It's an alias for a VariantN with an
appropriately-constructed maximum size. Algebraic is
useful when it is desirable to restrict what a discriminated type
could hold to the end of defining simpler and more efficient
manipulation.
Variant is an alias for VariantN instantiated with the largest of creal,
char[], and void delegate(). This ensures that Variant is large enough
to hold all of D's predefined types unboxed, including all numeric types,
pointers, delegates, and class references. You may want to use
VariantN directly with a different maximum size either for
storing larger types unboxed, or for saving memory.