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