TaggedUnion

Implements a generic tagged union type.

This struct takes a union or struct declaration as an input and builds an algebraic data type from its fields, using an automatically generated Kind enumeration to identify which field of the union is currently used. Multiple fields with the same value are supported.

For each field defined by U a number of convenience members are generated. For a given field "foo", these fields are:

  • static foo(value) - returns a new tagged union with the specified value
  • isFoo - equivalent to kind == Kind.foo
  • setFoo(value) - equivalent to set!(Kind.foo)(value)
  • getFoo - equivalent to get!(Kind.foo)
template TaggedUnion (
U
) if (
is(U == union) ||
is(U == struct)
||
is(U == enum)
) {}

Members

Structs

TaggedUnion
struct TaggedUnion
Undocumented in source.

Examples

union Kinds {
	int count;
	string text;
}
alias TU = TaggedUnion!Kinds;

// default initialized to the first field defined
TU tu;
assert(tu.kind == TU.Kind.count);
assert(tu.isCount); // equivalent to the line above
assert(!tu.isText);
assert(tu.value!(TU.Kind.count) == int.init);

// set to a specific count
tu.setCount(42);
assert(tu.isCount);
assert(tu.countValue == 42);
assert(tu.value!(TU.Kind.count) == 42);
assert(tu.value!int == 42); // can also get by type
assert(tu.countValue == 42);

// assign a new tagged algebraic value
tu = TU.count(43);

// test equivalence with other tagged unions
assert(tu == TU.count(43));
assert(tu != TU.count(42));
assert(tu != TU.text("hello"));

// modify by reference
tu.countValue++;
assert(tu.countValue == 44);

// set the second field
tu.setText("hello");
assert(!tu.isCount);
assert(tu.isText);
assert(tu.kind == TU.Kind.text);
assert(tu.textValue == "hello");

// unique types can also be directly constructed
tu = TU(12);
assert(tu.countValue == 12);
tu = TU("foo");
assert(tu.textValue == "foo");
// Enum annotations supported since DMD 2.082.0. The mixin below is
// necessary to keep the parser happy on older versions.
static if (__VERSION__ >= 2082) {
	alias myint = int;
	// tagged unions can be defined in terms of an annotated enum
	mixin(q{enum E {
		none,
		@string text
	}});

	alias TU = TaggedUnion!E;
	static assert(is(TU.Kind == E));

	TU tu;
	assert(tu.isNone);
	assert(tu.kind == E.none);

	tu.setText("foo");
	assert(tu.kind == E.text);
	assert(tu.textValue == "foo");
}

Meta