TaggedUnion is the low level tagged union functionality separated out
from TaggedAlgebraic. Because it doesn't support transparent access of
methods and operators of the contained value, it is able to provide a
number of convenience features. On top of that, visit and tryVisit is
now supported for pattern matching, analogous to the version for
std.variant.Algebraic. This is the basic usage:
union U {
string caption;
int height;
int width;
}
alias Value = TaggedUnion!U;
auto val = Value.caption("foo");
assert(val.kind == Value.Kind.caption);
assert(val.value!(Value.Kind.caption) == "foo");
// shorthand syntax:
assert(val.isCaption);
assert(val.captionValue == "foo");
// set a different type/kind
val.setHeight(10);
assert(val.isHeight && val.heightValue == 10);
assert(!val.isWidth);
assert(cast(short)val == 10);
val.visit!(
(int i) { assert(i == 10); }
(string s) { assert(false); }
);
assert(val.visit!((v) => v.to!string) == "10");
Another addition is a new placeholder "This" type to enable defining
self-referential types without having to write additional boilerplate code:
union U {
bool boolean;
string text;
float number;
TaggedUnion!This[] array;
TaggedUnion!This[string] object;
}
alias JsonValue = TaggedUnion!U;
The general advantages of TaggedUnion/TaggedAlgebraic over Algebraic
result from its use of a numeric type tag instead of relying on runtime
TypeInfo:
- Allows compiler checked handling of all possible types/kinds using
"final switch"
- Enables inlining and function attribute inference (@safe, nothrow,
@nogc)
- Allows to use the same type with multiple tags to avoid the overhead
of defining separate wrapper types
- Behaves like a POD if only POD fields exist, is non-copyable if any
contained type is non-copyable etc.
DUB: https://code.dlang.org/packages/taggedalgebraic
GitHub: https://github.com/s-ludwig/taggedalgebraic