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 !