blob: 374dd7852aa71b762b0f2e7fbf6483732a9f7b19 [file] [log] [blame]
@system unittest
{
import std.variant;
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");
// can also assign arrays
a = new int[42];
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
}
@safe unittest
{
import std.variant;
struct Cat { int a, b, c; }
align(1) struct S
{
long l;
ubyte b;
}
align(1) struct T
{
ubyte b;
long l;
}
static assert(maxSize!(int, long) == 8);
static assert(maxSize!(bool, byte) == 1);
static assert(maxSize!(bool, Cat) == 12);
static assert(maxSize!(char) == 1);
static assert(maxSize!(char, short, ubyte) == 2);
static assert(maxSize!(char, long, ubyte) == 8);
import std.algorithm.comparison : max;
static assert(maxSize!(long, S) == max(long.sizeof, S.sizeof));
static assert(maxSize!(S, T) == max(S.sizeof, T.sizeof));
static assert(maxSize!(int, ubyte[7]) == 7);
static assert(maxSize!(int, ubyte[3]) == 4);
static assert(maxSize!(int, int, ubyte[3]) == 4);
static assert(maxSize!(void, int, ubyte[3]) == 4);
static assert(maxSize!(void) == 1);
}
@system unittest
{
import std.variant;
alias Var = VariantN!(maxSize!(int, double, string));
Var a; // Must assign before use, otherwise exception ensues
// Initialize with an integer; make the type int
Var 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");
}
@system unittest
{
import std.variant;
alias Var = VariantN!(maxSize!(int[]));
Var a = new int[42];
assert(a.length == 42);
a[5] = 7;
assert(a[5] == 7);
}
@system unittest
{
import std.variant;
alias Var = VariantN!(maxSize!(int*)); // classes are pointers
Var a;
class Foo {}
auto foo = new Foo;
a = foo;
assert(*a.peek!(Foo) == foo); // and full type information is preserved
}
@system unittest
{
import std.variant;
auto v = Algebraic!(int, double, string)(5);
assert(v.peek!(int));
v = 3.14;
assert(v.peek!(double));
// auto x = v.peek!(long); // won't compile, type long not allowed
// v = '1'; // won't compile, type char not allowed
}
@system unittest
{
import std.variant;
import std.typecons : Tuple, tuple;
// A tree is either a leaf or a branch of two other trees
alias Tree(Leaf) = Algebraic!(Leaf, Tuple!(This*, This*));
Tree!int tree = tuple(new Tree!int(42), new Tree!int(43));
Tree!int* right = tree.get!1[1];
assert(*right == 43);
// An object is a double, a string, or a hash of objects
alias Obj = Algebraic!(double, string, This[string]);
Obj obj = "hello";
assert(obj.get!1 == "hello");
obj = 42.0;
assert(obj.get!0 == 42);
obj = ["customer": Obj("John"), "paid": Obj(23.95)];
assert(obj.get!2["customer"] == "John");
}
@system unittest
{
import std.variant;
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");
}
@system unittest
{
import std.variant;
Variant a = new int[42];
assert(a.length == 42);
a[5] = 7;
assert(a[5] == 7);
}
@system unittest
{
import std.variant;
Variant a;
class Foo {}
auto foo = new Foo;
a = foo;
assert(*a.peek!(Foo) == foo); // and full type information is preserved
}
@system unittest
{
import std.variant;
auto a = variantArray(1, 3.14, "Hi!");
assert(a[1] == 3.14);
auto b = Variant(a); // variant array as variant
assert(b[1] == 3.14);
}
@system unittest
{
import std.variant;
import std.exception : assertThrown;
Variant v;
// uninitialized use
assertThrown!VariantException(v + 1);
assertThrown!VariantException(v.length);
// .get with an incompatible target type
assertThrown!VariantException(Variant("a").get!int);
// comparison between incompatible types
assertThrown!VariantException(Variant(3) < Variant("a"));
}
@system unittest
{
import std.variant;
Algebraic!(int, string) variant;
variant = 10;
assert(variant.visit!((string s) => cast(int) s.length,
(int i) => i)()
== 10);
variant = "string";
assert(variant.visit!((int i) => i,
(string s) => cast(int) s.length)()
== 6);
// Error function usage
Algebraic!(int, string) emptyVar;
auto rslt = emptyVar.visit!((string s) => cast(int) s.length,
(int i) => i,
() => -1)();
assert(rslt == -1);
// Generic function usage
Algebraic!(int, float, real) number = 2;
assert(number.visit!(x => x += 1) == 3);
// Generic function for int/float with separate behavior for string
Algebraic!(int, float, string) something = 2;
assert(something.visit!((string s) => s.length, x => x) == 2); // generic
something = "asdf";
assert(something.visit!((string s) => s.length, x => x) == 4); // string
// Generic handler and empty handler
Algebraic!(int, float, real) empty2;
assert(empty2.visit!(x => x + 1, () => -1) == -1);
}
@system unittest
{
import std.variant;
Algebraic!(int, string) variant;
variant = 10;
auto which = -1;
variant.tryVisit!((int i) { which = 0; })();
assert(which == 0);
// Error function usage
variant = "test";
variant.tryVisit!((int i) { which = 0; },
() { which = -100; })();
assert(which == -100);
}