2016-01-27 22:08:17 +00:00
TaggedAlgebraic
===============
2019-02-22 10:30:31 +00:00
Implementation of a generic `TaggedUnion` type along with a `TaggedAlgebraic` type that forwards all methods and operators of the contained types using dynamic dispatch.
2016-01-27 22:08:17 +00:00
2018-01-17 23:02:06 +00:00
[![Build Status ](https://travis-ci.org/s-ludwig/taggedalgebraic.svg?branch=master )](https://travis-ci.org/s-ludwig/taggedalgebraic) [![codecov ](https://codecov.io/gh/s-ludwig/taggedalgebraic/branch/master/graph/badge.svg )](https://codecov.io/gh/s-ludwig/taggedalgebraic)
2016-09-20 04:48:32 +00:00
2019-02-22 10:30:31 +00:00
Usage of `TaggedUnion`
----------------------
```d
import taggedalgebraic;
struct Foo {
string name;
void bar() {}
}
union Base {
int count;
int offset;
string str;
Foo foo;
}
alias TUnion = TaggedUnion!Base;
// Instantiate
TUnion taggedInt = TUnion.count(5);
TUnion taggedString = TUnion.str("Hello");
TUnion taggedFoo = TUnion.foo;
TUnion taggedAny = taggedInt;
taggedAny = taggedString;
taggedAny = taggedFoo;
// Default initializes to the first field
TUnion taggedDef;
assert(taggedDef.isCount);
2019-02-22 15:11:21 +00:00
assert(taggedDef.countValue == int.init);
2019-02-22 10:30:31 +00:00
// Check type: TUnion.Kind is an enum
assert(taggedInt.kind == TUnion.Kind.count);
assert(taggedString.kind == TUnion.Kind.str);
assert(taggedFoo.kind == TUnion.Kind.foo);
assert(taggedAny.kind == TUnion.Kind.foo);
// A shorter syntax is also available
assert(taggedInt.isCount);
assert(!taggedInt.isOffset);
assert(taggedString.isStr);
assert(taggedFoo.isFoo);
assert(taggedAny.isFoo);
// Set to a different type
2019-04-16 10:11:14 +00:00
taggedAny.setStr("bar");
2019-02-22 10:30:31 +00:00
assert(taggedAny.isStr);
2019-02-22 15:11:21 +00:00
assert(taggedAny.strValue == "bar");
2019-02-22 10:30:31 +00:00
// Modify contained value by reference
2019-02-22 15:11:21 +00:00
taggedAny.strValue = "baz";
assert(taggedAny.strValue == "baz");
2019-02-22 10:30:31 +00:00
// In addition to the getter, the contained value can be extracted using get!()
// or by casting
2019-02-22 15:11:21 +00:00
assert(taggedInt.value!(TUnion.Kind.count) == 5);
assert(taggedInt.value!int == 5);
2019-02-22 10:30:31 +00:00
assert(cast(byte)taggedInt == 5);
// Multiple kinds of the same type are supported
taggedAny.setOffset(5);
assert(taggedAny.isOffset);
2019-02-22 15:11:21 +00:00
assert(!taggedAny.isCount);
// Unique types can also be set directly
taggedAny = "foo";
assert(taggedAny.isStr);
taggedAny = TUnion(Foo.init);
assert(taggedAny.isFoo);
2019-02-22 10:30:31 +00:00
```
Usage of `TaggedAlgebraic`
--------------------------
2016-09-20 04:48:32 +00:00
```d
import taggedalgebraic;
struct Foo {
string name;
void bar() {}
}
union Base {
int i;
string str;
Foo foo;
}
2019-02-22 10:30:31 +00:00
alias TAlgebraic = TaggedAlgebraic!Base;
2016-09-20 04:48:32 +00:00
// Instantiate
2019-02-22 10:30:31 +00:00
TAlgebraic taggedInt = 5;
TAlgebraic taggedString = "Hello";
TAlgebraic taggedFoo = Foo();
TAlgebraic taggedAny = taggedInt;
2016-09-20 04:48:32 +00:00
taggedAny = taggedString;
taggedAny = taggedFoo;
2019-02-22 10:30:31 +00:00
// Check type: TAlgebraic.Kind is an enum
assert(taggedInt.kind == TAlgebraic.Kind.i);
assert(taggedString.kind == TAlgebraic.Kind.str);
assert(taggedFoo.kind == TAlgebraic.Kind.foo);
assert(taggedAny.kind == TAlgebraic.Kind.foo);
2016-09-20 04:48:32 +00:00
// In most cases, can simply use as-is
auto num = 4 + taggedInt;
auto msg = taggedString ~ " World!";
taggedFoo.bar();
2019-02-22 10:30:31 +00:00
if (taggedAny.kind == TAlgebraic.Kind.foo) // Make sure to check type first!
2016-09-20 04:48:32 +00:00
taggedAny.bar();
//taggedString.bar(); // AssertError: Not a Foo!
// Convert back by casting
auto i = cast(int) taggedInt;
auto str = cast(string) taggedString;
auto foo = cast(Foo) taggedFoo;
2019-02-22 10:30:31 +00:00
if (taggedAny.kind == TAlgebraic.Kind.foo) // Make sure to check type first!
2016-09-20 04:48:32 +00:00
auto foo2 = cast(Foo) taggedAny;
//cast(Foo) taggedString; // AssertError!
// Kind is an enum, so final switch is supported:
final switch (taggedAny.kind) {
2019-02-22 10:30:31 +00:00
case TAlgebraic.Kind.i:
2016-09-20 04:48:32 +00:00
// It's "int i"
break;
2019-02-22 10:30:31 +00:00
case TAlgebraic.Kind.str:
2016-09-20 04:48:32 +00:00
// It's "string str"
break;
2019-02-22 10:30:31 +00:00
case TAlgebraic.Kind.foo:
2016-09-20 04:48:32 +00:00
// It's "Foo foo"
break;
}
```
2019-02-22 10:30:31 +00:00
Compiler support
----------------
The library is tested to work on the following compilers:
- DMD 2.076.1 up to 2.084.1
- LDC 1.6.0 up to 1.14.0