1 module more.taggedunion; 2 3 struct Tag 4 { 5 string name; 6 template opDispatch(string name) 7 { 8 enum opDispatch = Tag(name); 9 } 10 } 11 mixin template TaggedUnion(T...) 12 { 13 import std.conv : to; 14 private enum enumDefMixin = 15 "private enum TagEnum {\n" ~ function() { 16 string fields = ""; 17 foreach (item; T) 18 { 19 static if ( is(typeof(item) : Tag) ) 20 { 21 fields ~= " " ~ item.name ~ ",\n"; 22 } 23 } 24 return fields; 25 }() ~ "}\n"; 26 pragma(msg, enumDefMixin); 27 mixin(enumDefMixin); 28 29 private enum unionMixin = 30 "union {\n" ~ function() { 31 string result = ""; 32 static foreach (itemIndex; 0 .. T.length) 33 { 34 static if (itemIndex % 3 == 0) 35 { 36 } 37 else static if (itemIndex % 3 == 1) 38 { 39 static if ( !is(T[itemIndex] == void)) 40 { 41 result ~= " T[" ~ itemIndex.to!string ~ "] "; 42 } 43 } 44 else 45 { 46 static if (T[itemIndex] !is null) 47 { 48 result ~= T[itemIndex] ~ ";\n"; 49 } 50 } 51 } 52 return result; 53 }() ~ "}\n"; 54 pragma(msg, unionMixin); 55 mixin(unionMixin); 56 TagEnum tag; 57 } 58 unittest 59 { 60 struct PassOrFail 61 { 62 mixin TaggedUnion!( 63 Tag.pass, void, null, 64 Tag.fail, int, "errorCode"); 65 } 66 auto result = PassOrFail(); 67 }