vibe.d beta banner
get vibe.d
0.8.5

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

Struct TaggedUnion

Implements a generic tagged union type.

struct TaggedUnion(U)
  
if (is(U == union) || 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.

For each field defined by U a number of convenience members are generated. For a given field "foo", these fields are:

  • static foo(value)
  • - returns a new tagged union with the specified value
  • isFoo - equivalent to kind == Kind.foo
  • setFoo(value) - equivalent to set!(Kind.foo)(value)
  • getFoo - equivalent to get!(Kind.foo)
  • )

    Constructors

    NameDescription
    this
    this

    Fields

    NameTypeDescription
    m_data void[Largest!FieldTypes.sizeof]
    m_kind TaggedUnion.Kind

    Properties

    NameTypeDescription
    hasType[get] boolChecks whether the currently stored value has a given type.
    kind[get] TaggedUnion.KindThe type ID of the currently stored value.
    trustedGet[get] inout(T)
    value[get] inout(TaggedUnion.FieldTypes[kind])Accesses the contained value by reference.
    value[get] inout(T)Accesses the contained value by reference.

    Methods

    NameDescription
    opAssign
    opCast Enables conversion or extraction of the stored value.
    opEquals Enables equality comparison with the stored value.
    set Sets a new value of the specified kind.
    set Sets a void value of the specified kind.

    Aliases

    NameDescription
    FieldDefinitionType
    fieldNames
    FieldTypeByName
    FieldTypes
    Kind A type enum that identifies the type of value currently stored.

    Example

    union Kinds {
    	int count;
    	string text;
    }
    alias TU = TaggedUnion!Kinds;
    
    // default initialized to the first field defined
    TU tu;
    assert(tu.kind == TU.Kind.count);
    assert(tu.isCount); // qequivalent to the line above
    assert(!tu.isText);
    assert(tu.value!(TU.Kind.count) == int.init);
    
    // set to a specific count
    tu.setCount(42);
    assert(tu.isCount);
    assert(tu.countValue == 42);
    assert(tu.value!(TU.Kind.count) == 42);
    assert(tu.value!int == 42); // can also get by type
    assert(tu.countValue == 42);
    
    // assign a new tagged algebraic value
    tu = TU.count(43);
    
    // test equivalence with other tagged unions
    assert(tu == TU.count(43));
    assert(tu != TU.count(42));
    assert(tu != TU.text("hello"));
    
    // modify by reference
    tu.countValue++;
    assert(tu.countValue == 44);
    
    // set the second field
    tu.setText("hello");
    assert(!tu.isCount);
    assert(tu.isText);
    assert(tu.kind == TU.Kind.text);
    assert(tu.textValue == "hello");
    
    // unique types can also be directly constructed
    tu = TU(12);
    assert(tu.countValue == 12);
    tu = TU("foo");
    assert(tu.textValue == "foo");
    

    Example

    // Enum annotations supported since DMD 2.082.0. The mixin below is
    // necessary to keep the parser happy on older versions.
    static if (__VERSION__ >= 2082) {
    	alias myint = int;
    	// tagged unions can be defined in terms of an annotated enum
    	mixin(q{enum E {
    		none,
    		@string text
    	}});
    
    	alias TU = TaggedUnion!E;
    	static assert(is(TU.Kind == E));
    
    	TU tu;
    	assert(tu.isNone);
    	assert(tu.kind == E.none);
    
    	tu.setText("foo");
    	assert(tu.kind == E.text);
    	assert(tu.textValue == "foo");
    }
    
    Authors

    Sönke Ludwig

    Copyright

    Copyright 2015-2019, Sönke Ludwig.

    License

    www.boost.org/LICENSE_1_0.txt, Boost License 1.0.