1 module evx.meta.transform; 2 3 private {//imports 4 import std.traits; 5 import std.typecons; 6 import evx.meta.match; 7 } 8 9 /** 10 identity template 11 */ 12 alias Identity (T...) = T[0]; 13 /// 14 unittest { 15 static assert (is (Identity!int == int)); 16 } 17 18 /** 19 identity function 20 */ 21 auto ref identity (T)(T x) 22 { 23 return x; 24 } 25 /// 26 unittest { 27 assert (1.identity == 1); 28 } 29 30 /** 31 get the type of a single-symbol expression 32 */ 33 template ExprType (alias symbol) 34 { 35 alias ExprType = typeof(symbol.identity); 36 } 37 /// 38 unittest { 39 auto a (){return 1;} 40 auto b = 1; 41 42 static assert (!(is (typeof(a) == typeof(b)))); 43 static assert (is (typeof(a()) == typeof(b))); 44 static assert (is (typeof(a()) == ExprType!a)); 45 static assert (is (ExprType!a == ExprType!b)); 46 } 47 48 /** 49 remove qualifiers from a type 50 */ 51 alias Unqual = std.traits.Unqual; 52 53 /** 54 select one of two valid expressions based on a boolean expression 55 */ 56 alias Select = std.typecons.Select; 57 58 /** 59 extract the underlying type of a unary template type 60 */ 61 template Unwrapped (T) 62 { 63 static if (is (T == W!U, alias W, U)) 64 alias Unwrapped = U; 65 else alias Unwrapped = T; 66 } 67 /// 68 unittest { 69 static struct T {} 70 static struct U (T) {} 71 72 alias V = U!T; 73 alias W = U!(U!T); 74 75 static assert (is (Unwrapped!T == T)); 76 static assert (is (Unwrapped!V == T)); 77 static assert (is (Unwrapped!W == V)); 78 static assert (is (Unwrapped!(Unwrapped!W) == T)); 79 } 80 81 /** 82 extract the deepest underlying type of a nested series of unary templates 83 */ 84 template InitialType (T) 85 { 86 static if (is (T == W!U, alias W, U)) 87 alias InitialType = InitialType!U; 88 else alias InitialType = T; 89 } 90 /// 91 unittest { 92 static struct T {} 93 static struct U (T) {} 94 95 alias V = U!T; 96 alias W = U!(U!T); 97 98 static assert (is (InitialType!T == T)); 99 static assert (is (InitialType!V == T)); 100 static assert (is (InitialType!W == T)); 101 } 102 103 /** 104 compose a list of templates into a single template 105 */ 106 template Compose (Templates...) 107 { 108 static if (Templates.length > 1) 109 { 110 alias T = Templates[0]; 111 alias U = Compose!(Templates[1..$]); 112 113 alias Compose (Args...) = T!(U!(Args)); 114 } 115 else alias Compose = Templates[0]; 116 } 117 /// 118 unittest { 119 import std.range: ElementType; 120 121 alias ArrayOf (T) = T[]; 122 alias Const (T) = const(T); 123 124 alias C0 = Compose!(ElementType, ArrayOf); 125 alias C1 = Compose!(ArrayOf, ElementType); 126 alias C2 = Compose!(ElementType, Const, C0); 127 alias C3 = Compose!(ArrayOf, Unqual, C2); 128 129 alias T = int[5]; 130 131 static assert (is (C0!T == int[5])); 132 static assert (is (C1!T == int[])); 133 static assert (is (C2!T == const(int))); 134 static assert (is (C3!T == int[])); 135 } 136 137 /** 138 mixin a zero-parameter template 139 (useful for mixing in templates from a list) 140 */ 141 template Mixin (alias mix) 142 { 143 mixin mix; 144 }