1 module memutils.helpers; 2 public: 3 4 template UnConst(T) { 5 static if (is(T U == const(U))) { 6 alias UnConst = U; 7 } else static if (is(T V == immutable(V))) { 8 alias UnConst = V; 9 } else alias UnConst = T; 10 } 11 12 /// TODO: Imitate Unique! for all objects (assume dtor) with release() 13 /// TODO: implement @override on underlying type T, and check for shadowed members. 14 mixin template Embed(alias OBJ, alias OWNED) 15 { 16 import std.traits : hasMember; 17 alias TR = typeof(OBJ); 18 static if (is(typeof(*OBJ) == struct)) 19 alias T = typeof(*OBJ); 20 else 21 alias T = TR; 22 23 import std.traits : isSomeFunction; 24 static if (!isSomeFunction!OBJ) 25 @property ref const(T) fallthrough() const 26 { 27 static if (__traits(hasMember, typeof(this), "defaultInit")) { 28 (cast(typeof(this)*)&this).defaultInit(); 29 checkInvariants(); 30 } 31 static if (is(TR == T*)) return *OBJ; 32 else return OBJ; 33 } 34 35 @property ref T fallthrough() 36 { 37 static if (__traits(hasMember, typeof(this), "defaultInit")) { 38 defaultInit(); 39 checkInvariants(); 40 } 41 static if (is(TR == T*)) return *OBJ; 42 else return OBJ; 43 } 44 45 @property ref const(T) opUnary(string op)() const if (op == "*") 46 { 47 return (cast(typeof(this)*)&this).fallthrough; 48 } 49 50 51 alias fallthrough this; 52 53 static if (!isSomeFunction!OBJ) 54 @property TR release() { 55 static if (__traits(hasMember, typeof(this), "defaultInit")) { 56 defaultInit(); 57 checkInvariants(); 58 } 59 TR ret = OBJ; 60 OBJ = null; 61 return ret; 62 } 63 64 auto opBinaryRight(string op, Key)(Key key) 65 inout if (op == "in" && __traits(hasMember, typeof(OBJ), "opBinaryRight")) { 66 defaultInit(); 67 return fallthrough().opBinaryRight!("in")(key); 68 } 69 70 bool opEquals(U)(auto ref U other) const 71 { 72 defaultInit(); 73 return fallthrough().opEquals(other); 74 } 75 76 int opCmp(U)(auto ref U other) const 77 { 78 defaultInit(); 79 return fallthrough().opCmp(other); 80 } 81 82 int opApply(U...)(U args) 83 if (__traits(hasMember, typeof(OBJ), "opApply")) 84 { 85 defaultInit(); 86 return fallthrough().opApply(args); 87 } 88 89 int opApply(U...)(U args) const 90 if (__traits(hasMember, typeof(OBJ), "opApply")) 91 { 92 defaultInit(); 93 return fallthrough().opApply(args); 94 } 95 96 void opSliceAssign(U...)(U args) 97 if (__traits(hasMember, typeof(OBJ), "opSliceAssign")) 98 { 99 defaultInit(); 100 fallthrough().opSliceAssign(args); 101 } 102 103 104 auto opSlice(U...)(U args) const 105 if (__traits(hasMember, typeof(OBJ), "opSlice")) 106 { 107 defaultInit(); 108 return (cast()fallthrough()).opSlice(args); 109 110 } 111 112 static if (__traits(hasMember, typeof(OBJ), "opDollar")) 113 size_t opDollar() const 114 { 115 return fallthrough().opDollar(); 116 } 117 118 void opOpAssign(string op, U...)(auto ref U args) 119 if (__traits(compiles, fallthrough().opOpAssign!op(args))) 120 { 121 defaultInit(); 122 fallthrough().opOpAssign!op(args); 123 } 124 125 auto opBinary(string op, U...)(auto ref U args) 126 if (__traits(compiles, fallthrough().opBinary!op(args))) 127 { 128 defaultInit(); 129 return fallthrough().opBinary!op(args); 130 } 131 132 void opIndexAssign(U, V)(auto const ref U arg1, auto const ref V arg2) 133 if (__traits(hasMember, typeof(fallthrough()), "opIndexAssign")) 134 { 135 defaultInit(); 136 fallthrough().opIndexAssign(arg1, arg2); 137 } 138 139 auto ref opIndex(U...)(U args) inout 140 if (__traits(hasMember, typeof(fallthrough()), "opIndex")) 141 { 142 return fallthrough().opIndex(args); 143 } 144 145 static if (__traits(compiles, fallthrough().opBinaryRight!("in")(ReturnType!(fallthrough().front).init))) 146 bool opBinaryRight(string op, U)(auto ref U e) const if (op == "in") 147 { 148 defaultInit(); 149 return fallthrough().opBinaryRight!("in")(e); 150 } 151 }