The OpenD Programming Language

TaggedVariant

Tagged Variant Type (aka Tagged Algebraic Type).

Compatible with BetterC mode.

Template has two declarations:

// and
template TaggedVariant(T)
    if (is(T == union))
{
    ...
}
deprecated
template TaggedVariant (
T
) if (
is(T == union)
) {}

Examples

Json Value with styles

1 enum Style { block, flow }
2 
3 static struct SomeMetadata {
4     int a;
5     @safe pure nothrow @nogc scope
6     int opCmp(scope const SomeMetadata rhs) const { return a - rhs.a; }
7 }
8 
9 static struct ParsePosition
10 {
11     string file, line, column;
12 
13     void toString()(scope ref W w) scope const
14     {
15         w.put(file);
16         if (line) {
17             w.put("("); w.put(line);
18             if (column) { w.put(","); w.put(column); }
19             w.put(")");
20         }
21     }
22 }
23 
24 static union Json_
25 {
26     typeof(null) null_;
27     bool boolean;
28     long integer;
29     double floating;
30     // Not, that `string` is't builtin type but an alias in `object.d`
31     // So we can use `string` as a name of the string field
32     immutable(char)[] string;
33     This[] array;
34     // commented out to test `opCmp` primitive
35     // This[immutable(char)[]] object;
36 
37 @algMeta:
38     bool active;
39     SomeMetadata metadata;
40 @algTransp:
41     Style style;
42     @algVerbose ParsePosition position;
43 }
44 
45 alias JsonAlgebraic = Algebraic!Json_;
46 
47 // typeof(null) has priority
48 static assert(JsonAlgebraic.Kind.init == JsonAlgebraic.Kind.null_);
49 static assert(JsonAlgebraic.Kind.null_ == 0);
50 
51 // Kind and AllowedTypes has the same order
52 static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.array] == JsonAlgebraic[]));
53 static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.boolean] == bool));
54 static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.floating] == double));
55 static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.integer] == long));
56 static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.null_] == typeof(null)));
57 // static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.object] == JsonAlgebraic[string]));
58 
59 JsonAlgebraic v;
60 assert(v.kind == JsonAlgebraic.Kind.null_);
61 
62 v = 1;
63 assert(v.kind == JsonAlgebraic.Kind.integer);
64 assert(v == 1);
65 v = JsonAlgebraic(1);
66 assert(v == 1);
67 v = v.get!(long, double);
68 
69 v = "Tagged!";
70 // member-based access. Simple!
71 assert(v.string == "Tagged!");
72 // type-based access
73 assert(v.get!string == "Tagged!");
74 assert(v.trustedGet!string == "Tagged!");
75 
76 assert(v.kind == JsonAlgebraic.Kind.string);
77 
78 assert(v.get!"string" == "Tagged!"); // string-based get
79 assert(v.trustedGet!"string" == "Tagged!"); // string-based trustedGet
80 
81 assert(v.get!(JsonAlgebraic.Kind.string) == "Tagged!"); // Kind-based get
82 assert(v.trustedGet!(JsonAlgebraic.Kind.string) == "Tagged!"); // Kind-based trustedGet
83 
84 // checks
85 assert(v._is!string); // type based
86 assert(v._is!"string"); // string based
87 assert(v._is!(JsonAlgebraic.Kind.string)); //
88 
89 v = null;
90 assert(v.kind == JsonAlgebraic.Kind.null_);
91 
92 v = [JsonAlgebraic("str"), JsonAlgebraic(4.3)];
93 
94 assert(v.kind == JsonAlgebraic.Kind.array);
95 assert(v.trustedGet!(JsonAlgebraic[])[1].kind == JsonAlgebraic.Kind.floating);
96 
97 JsonAlgebraic w = v;
98 w.style = Style.flow;
99 assert(v.style != w.style);
100 assert(v == w);
101 assert(v <= w);
102 assert(v >= w);
103 assert(v.toHash == w.toHash);
104 w.active = true;
105 assert(v != w);
106 assert(v.toHash != w.toHash);
107 assert(v.get!"array" == w.get!"array");
108 assert(v < w);
109 
110 // test equality with self-referencing allowed type
111 auto arr = [JsonAlgebraic("str"), JsonAlgebraic(120)];
112 v = arr;
113 assert(v == arr);
114 assert(v == [JsonAlgebraic("str"), JsonAlgebraic(120)]);

Wrapped algebraic with propogated primitives

static struct Response
{
    private union Response_
    {
        double float_;
        immutable(char)[] string;
        Response[] array;
        Response[immutable(char)[]] table;
    }

    alias ResponseAlgebraic = Algebraic!Response_;

    ResponseAlgebraic data;
    alias Tag = ResponseAlgebraic.Kind;

    // propogates opEquals, opAssign, and other primitives
    alias data this;

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

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

See Also

Meta