1 module tame.meta; 2 3 import std.traits; 4 import std.meta : AliasSeq; 5 6 template staticIota(int beg, int end) { 7 static if (beg + 1 >= end) { 8 static if (beg >= end) { 9 alias staticIota = AliasSeq!(); 10 } else { 11 alias staticIota = AliasSeq!beg; 12 } 13 } else { 14 enum mid = beg + (end - beg) / 2; 15 alias staticIota = AliasSeq!(staticIota!(beg, mid), staticIota!(mid, end)); 16 } 17 } 18 19 template getUDA(alias sym, T) { 20 static foreach (uda; __traits(getAttributes, sym)) 21 static if (is(typeof(uda) == T)) 22 alias getUDA = uda; 23 static if (is(typeof(getUDA) == void)) 24 alias getUDA = T.init; 25 } 26 27 alias CutOut(size_t I, T...) = AliasSeq!(T[0 .. I], T[I + 1 .. $]); 28 29 /** 30 * Generates a mixin string for repeating code. It can be used to unroll variadic arguments. 31 * A format string is instantiated a certain number times with an incrementing parameter. 32 * The results are then concatenated using an optional joiner. 33 * 34 * Params: 35 * length = Number of elements you want to join. It is passed into format() as an incrementing number from [0 .. count$(RPAREN). 36 * fmt = The format string to apply on each instanciation. Use %1d$ to refer to the current index multiple times when necessary. 37 * joiner = Optional string that will be placed between instances. It could be a space or an arithmetic operation. 38 * 39 * Returns: 40 * The combined elements as a mixin string. 41 * 42 * See_Also: 43 * $(LINK2 http://forum.dlang.org/thread/vqfvihyezbmwcjkmpzin@forum.dlang.org, A simple way to do compile time loop unrolling) 44 */ 45 enum ctfeJoin(size_t length)(in string fmt, in string joiner = null) { 46 import std.range : iota; 47 import std.algorithm : map; 48 49 // BUG: Cannot use, join(), as it "cannot access the nested function 'ctfeJoin'". 50 string result; 51 foreach (inst; map!(i => format(fmt, i))(iota(length))) { 52 if (result && joiner) 53 result ~= joiner; 54 result ~= inst; 55 } 56 return result; 57 } 58 59 auto ParameterDefaultsCount(func...)() { 60 template PDC(alias func, int cnt) { 61 static if (__traits(compiles, func(Parameters!func[0 .. cnt]))) 62 enum PDC = PDC!(func, cnt - 1); 63 else 64 enum PDC = arity!func - cnt; 65 } 66 67 size_t n; 68 static foreach (f; func) 69 n += PDC!(f, arity!f); 70 return n; 71 } 72 73 unittest { 74 import tame.ascii; 75 76 static assert(ParameterDefaultsCount!classify == 0); 77 } 78 79 /++ 80 `_` is a enum that provides overloaded `=` operator. That overload takes a value and promptly throws it away. 81 Examples: 82 --- 83 _ = 2 + 3; 84 _ = new A(); 85 --- 86 +/ 87 enum _ = Impl(); 88 89 private struct Impl { 90 /++ 91 Take an argument, throw it away and do nothing. 92 Params: 93 first = value to be ignored. 94 +/ 95 pragma(inline, true); 96 void opAssign(T)(in T) inout { 97 } 98 } 99 100 unittest { 101 _ = 2; 102 _ = _; 103 } 104 105 /++ 106 A copy of std::tie from C++. 107 TODO: write proper documentation for this 108 Examples: 109 --- 110 int a; 111 string b; 112 tie(a, b) = tuple(3, "hi"); 113 assert(a == 3 && b == hi); 114 --- 115 +/ 116 auto tie(T...)(out T args) { 117 struct Impl { 118 void opAssign(U)(U tuple) if (U.length == T.length) { 119 static foreach (i; 0 .. U.length) 120 args[i] = tuple[i]; 121 } 122 } 123 124 return Impl(); 125 }