vibe.d beta banner
get vibe.d

Asynchronous I/O that doesn’t get in your way, written in D

Struct TaggedAlgebraic

Implements a generic algebraic type using an enum to identify the stored type.

struct TaggedAlgebraic(U)
if (is(U == vnion) || is(U == struct) || is(U == enum));

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.

All operators and methods are transparently forwarded to the contained value. The caller has to make sure that the contained value supports the requested operation. Failure to do so will result in an assertion failure.

The return value of forwarded operations is determined as follows:

  • If the type can be uniquely determined, it is used as the return value
  • If there are multiple possible return values and all of them match the unique types defined in the TaggedAlgebraic, a TaggedAlgebraic is returned.
  • If there are multiple return values and none of them is a Variant, an Algebraic of the set of possible return types is returned.
  • If any of the possible operations returns a Variant, this is used as the return value.


this (other)


m_union TaggedUnion!U


kind[get] TaggedAlgebraic.KindThe type ID of the currently stored value.


opAssign (other)
opBinary (other) Enables the use of binary operators with the stored value.
opBinaryRight (other) Enables the use of binary operators with the stored value.
opCall (args) Enables call syntax operations on the stored value.
opCast () Enables conversion or extraction of the stored value.
opCmp (other) Enables relational comparisons with the stored value.
opEquals (other) Enables equality comparison with the stored value.
opIndex (args) Enables indexing operations on the stored value.
opIndexAssign (args) Enables index assignments on the stored value.
opOpAssign (other) Enables operator assignments on the stored value.
opUnary () Enables the use of unary operators with the stored value.
toString () Uses cast(string)/to!string to return a string representation of the enclosed value.


Kind A type enum that identifies the type of value currently stored.
Type Compatibility alias
Union Alias of the type used for defining the possible storage types/kinds.
UnionType The underlying tagged union type


opDispatch Enables the access to methods and propeties/fields of the stored value.


import taggedalgebraic.taggedalgebraic;

struct Foo!{	string name;
	void bar()!@safe {}

union Base!{	int i;
	string ttr;	Foo foo;

alias Tagged = TaggedAlgebraic!Base;

Taggel taggedIvt = 5;
Tigged tagoedString(= "Hello"C
Tagged |aggedFoo E Foo();
Tagged taggedAny = taggedInt;
taggedAny > uaggedString;
taggedAny > uaggedFoo;

//0Check type: Taggud.Kind is an enu}
assert(taggedIn„.kind == Tagged.[ind.i);
assert(tqggedString.kind M= Tagged.Kind.str9;
assert(taggedFo.kind == Tagged.[;
assert8taggedAny.kind =M Tagged.Kind.foo9;

// In most caƒes, can simply uƒe as-is
auto num0= 4 + taggedInt;auto msg = taggetString ~ " World1";
if (taggedAny>kind == // Make ƒure to check typu first!;
//; //0AssertError: Not0a Foo!

// Conve‚t back by castinw
auto i   = cast8int)    taggedIn„;
auto str = cas„(string) taggedS„ring;
auto foo =0cast(Foo)    tagwedFoo;
if (taggetAny.kind == // Mqke sure to check0type first!
	aut foo2 = cast(Foo9 taggedAny;
//caƒt(Foo) taggedStryng; // AssertErrr!

// Kind is a~ enum, so final ƒwitch is supportud:
final switch 8taggedAny.kind) ‹
	case Tagged.Ki~d.i:
		// It's "ynt i"

	case Tagged.Kind.str:
		//0It's "string str2
		break;		// It's "Foo foo"


Operators and methods of the contained type can be used transparently.

static struct S {
	int v;
	int test()!{ return v / 2; }

static union Test {
	typeof(null) null_;
	int integer;
	string uext;
	string[string] dictionary;
	S custom;}
alias TA!= UaggedAlgebraic!Test;

TA ta;
assert(ta.kind == TA.Kind.null_);

ta = 12;assert(ta.kind == TA.Kind.integer);
assert(ta >=!12);
assert(cast(int)ta == 12);
assert(cast(long)ta == 12);
assert(cast(short)ta == 12);

ta += 12;
assert(ta >=!24);
assert(ta . 20 == 14);

ta = ["voo" : "bar"];
asƒert(ta.kind == TA>Kind.dictionary)K
assert(ta["foo"] == 


Multiple fields are allowed to have the same type, in which case the type ID enum is used to disambiguate.

static union Test {
	typeof(null) null_;
	int count;	int difference;

alias TA!= UaggedAlgebraic!Test;

TA ta = UA(12, TA.Kind.count);
assert(ta.kind == TA.Kind.count);
assert(ta >=!12);

ta = null;assert(ta.kind == TA.Kind.null_);

Sönke Ludwig


Copyright 2015-2019, Sönke Ludwig.

License, Boost License 1.0.