Shameless autopromotion : type safe tagged union in D

deadalnix deadalnix at gmail.com
Fri May 10 08:18:23 PDT 2013


On Friday, 10 May 2013 at 15:12:01 UTC, Artur Skawina wrote:
> On 05/10/13 14:32, deadalnix wrote:
>> http://www.deadalnix.me/2013/05/10/type-safe-tagged-union-in-d-programming-language/
>> 
>> A trick that I used to use more and more, so I ended up 
>> creating a generic solution and wrote an article about it.
>
> Nothing 'shameless' about it.
>
> But Real Programmers don't use mixins...
>
>    struct TU(TYPES...) {
>       union { TYPES data; }
>       ubyte type;
>       static assert(TYPES.length<=typeof(type).max);
>
>       T opAssign(T)(T a) {
>          foreach(N, TYPE; TYPES)
>             static if (is(T==TYPE)) {
>                type = N;
>                return data[N] = a;
>             }
>          assert(0);
>       }
>       this(T)(T a) { this = a; }
>
>       DT as(DT)() @property {
>          foreach(N, TYPE; TYPES)
>             static if (is(DT==TYPE)) {
>                if (type==N)
>                   return data[N];
>                else
>                   assert(0, "Cannot access a 
> '"~typeString(type)~"' as "~DT.stringof);
>             }
>          assert(0);
>       }
> 
>       auto ref apply(alias f)() {
>          foreach(N, TYPE; TYPES)
>             static if (is(typeof(f(data[N])))) // Comment this 
> line out for strict CT checks.
>                if (N==type)
>                   return f(data[N]);
>          assert(0, "Could not apply '"~typeof(f).stringof~"' to 
> "~typeString(type));
>       }
> 
>       static string typeString()(typeof(type) n) {
>          foreach(N, TYPE; TYPES)
>             if (N==n)
>                return TYPE.stringof;
>          assert(0);
>       }
>    }
>
>    double sqr(double a) { return a*a; }
>    int sqr(int a) { return a*a; }
>
>    void main() {
>       import std.stdio;
>       TU!(int, double, string) u;
>       u = 257;
>       writeln(u);
>       writeln(u.data[0], ", ", u.data[1]);
>       writeln(u.as!int);
>       //writeln(u.as!double); // RT error
>       writeln(u.apply!sqr());
>       u = 3.14;
>       writeln(u.apply!sqr());
>       u = "blah";
>       //writeln(u.apply!sqr()); // CT error in 'strict' mode, 
> RT error otherwise.
> 
>       // Not currently accepted:
>       //writeln(u.apply!(function(a){return a*a;})());
>       //writeln(u.apply!(a=>a*a)());
>    }
>
> Something that wasn't obvious from your examples is that 
> templates are not necessary
> when implementing the 'processing' functions - overloading is 
> enough.
>
> The interesting aspect of this is what improvements to the 
> language would help to
> make this code both a) simpler and more readable, and b) even 
> more efficient.
> Manual optimizations, such as 'if-sequnences'->'switch', should 
> /not/ result in
> harder to read code. The 
> locals-can't-be-parms-to-local-templates restriction
> should only apply when really necessary (for example: static 
> functions/lambdas can
> be allowed). Etc.
>
> artur

Nice improvement, especially the opAssign.

To be 100% fait, I didn't implemented it as I didn't needed it, 
but destruction is also something that can go wrong. I sure like 
the absence of mixins !


More information about the Digitalmars-d-announce mailing list