TaggedVariant

Tagged Variant Type (aka Tagged Algebraic Type).

Compatible with BetterC mode.

Template has two declarations:

alias TaggedVariant(string[] tags, T...) = Variant!(applyTags!(tags, T));
// and
template TaggedVariant(T)
    if (is(T == union))
{
    ...
}
  1. alias TaggedVariant(string[] tags, T...) = Variant!(applyTags!(tags, T))
    alias TaggedVariant(string[] tags, T...) = Variant!(applyTags!(tags, T))
  2. template TaggedVariant(T)

Examples

Json Value

static union JsonUnion
{
    long integer;
    double floating;
    bool boolean;
    typeof(null) null_;
    string string_;
    This[] array;
    This[string] object;
}

alias JsonValue = TaggedVariant!JsonUnion;

// typeof(null) has priority
static assert(JsonValue.Kind.init == JsonValue.Kind.null_);
static assert(JsonValue.Kind.null_ == 0);

// Kind and AllowedTypes has the same order
static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.array] == JsonValue[]));
static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.boolean] == bool));
static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.floating] == double));
static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.integer] == long));
static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.null_] == typeof(null)));
static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.object] == JsonValue[string]));

JsonValue v;
assert(v.kind == JsonValue.Kind.null_);

v = 1;
assert(v.kind == JsonValue.Kind.integer);
assert(v == 1);
v = JsonValue(1);
assert(v == 1);
v = v.get!(long, double);

v = "Tagged!";
assert(v.get       !string                  == "Tagged!");
assert(v.trustedGet!string                  == "Tagged!");

assert(v.kind == JsonValue.Kind.string_);

assert(v.get       !(JsonValue.Kind.string_) == "Tagged!"); // Kind-based get
assert(v.trustedGet!(JsonValue.Kind.string_) == "Tagged!"); // Kind-based trustedGet

v = [JsonValue("str"), JsonValue(4.3)];

assert(v.kind == JsonValue.Kind.array);
assert(v.trustedGet!(JsonValue[])[1].kind == JsonValue.Kind.floating);

v = null;
assert(v.kind == JsonValue.Kind.null_);

Wrapped algebraic with propogated primitives

static struct Response
{
    alias Union = TaggedVariant!(
        ["double_", "string", "array", "table"],
        double,
        string,
        Response[],
        Response[string],
    );

    Union data;
    alias Tag = Union.Kind;
    // propogates opEquals, opAssign, and other primitives
    alias data this;

    static foreach (T; Union.AllowedTypes)
        this(T v) @safe pure nothrow @nogc { data = v; }
}

Response v = 3.0;
assert(v.kind == Response.Tag.double_);
v = "str";
assert(v == "str");

See Also

Meta