Module std.variant
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.
A Variant
object 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 Variant
object. To read back the value of
the appropriate type T
, use the get
method. To query whether a
Variant
currently holds a value of type T
, use peek
. 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
).
Warning: Algebraic
is outdated and not recommended for use in new
code. Instead, use SumType
.
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.
Example
Variant a; // Must assign before use, otherwise exception ensues
// Initialize with an integer; make the type int
Variant b = 42;
writeln(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;
writeln(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";
writeln(a); // "now I'm a string"
// can also assign arrays
a = new int[42];
writeln(a .length); // 42
a[5] = 7;
writeln(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
Functions
Name | Description |
---|---|
variantArray(args)
|
Returns an array of variants constructed from args .
|
Classes
Name | Description |
---|---|
VariantException
|
Thrown in three cases: |
Structs
Name | Description |
---|---|
VariantN
|
Back-end type seldom used directly by user
code. Two commonly-used types using VariantN are:
|
Templates
Name | Description |
---|---|
tryVisit
|
Behaves as visit but doesn't enforce that all types are handled
by the visiting functions.
|
visit
|
Applies a delegate or function to the given Algebraic depending on the held type,
ensuring that all types are handled by the visiting functions.
|
Manifest constants
Name | Type | Description |
---|---|---|
maxSize
|
Gives the sizeof the largest type given.
|
Aliases
Name | Type | Description |
---|---|---|
Algebraic
|
VariantN!(maxSize!T,T)
|
Algebraic data type restricted to a closed set of possible
types. It's an alias for 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
|
VariantN!(32L)
|
Alias for VariantN instantiated with the largest size 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.
|