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) 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 23 static if (!__traits(hasMember, typeof(this), "defaultInit")) { 24 void defaultInit() const {} 25 } 26 static if (!__traits(hasMember, typeof(this), "checkInvariants")) { 27 void checkInvariants() const {} 28 } 29 @property ref const(T) opStar() const 30 { 31 (cast(typeof(this)*)&this).defaultInit(); 32 checkInvariants(); 33 static if (is(TR == T*)) return *OBJ; 34 else return OBJ; 35 } 36 37 @property ref T opStar() { 38 defaultInit(); 39 checkInvariants(); 40 static if (is(TR == T*)) return *OBJ; 41 else return OBJ; 42 } 43 44 alias opStar this; 45 46 auto opBinaryRight(string op, Key)(Key key) 47 inout if (op == "in" && __traits(hasMember, typeof(OBJ), "opBinaryRight")) { 48 defaultInit(); 49 return opStar().opBinaryRight!("in")(key); 50 } 51 52 bool opEquals(U)(auto ref U other) const 53 { 54 defaultInit(); 55 return opStar().opEquals(other); 56 } 57 58 int opCmp(U)(auto ref U other) const 59 { 60 defaultInit(); 61 return opStar().opCmp(other); 62 } 63 64 int opApply(U...)(U args) 65 if (__traits(hasMember, typeof(OBJ), "opApply")) 66 { 67 defaultInit(); 68 return opStar().opApply(args); 69 } 70 71 int opApply(U...)(U args) const 72 if (__traits(hasMember, typeof(OBJ), "opApply")) 73 { 74 defaultInit(); 75 return opStar().opApply(args); 76 } 77 78 void opSliceAssign(U...)(U args) 79 if (__traits(hasMember, typeof(OBJ), "opSliceAssign")) 80 { 81 defaultInit(); 82 opStar().opSliceAssign(args); 83 } 84 85 86 auto opSlice(U...)(U args) const 87 if (__traits(hasMember, typeof(OBJ), "opSlice")) 88 { 89 defaultInit(); 90 static if (is(U == void)) 91 return opStar().opSlice(); 92 else 93 return opStar().opSlice(args); 94 95 } 96 97 static if (__traits(hasMember, typeof(OBJ), "opDollar")) 98 size_t opDollar() const 99 { 100 return opStar().opDollar(); 101 } 102 103 void opOpAssign(string op, U...)(auto ref U args) 104 if (__traits(compiles, opStar().opOpAssign!op(args))) 105 { 106 defaultInit(); 107 opStar().opOpAssign!op(args); 108 } 109 110 auto opBinary(string op, U...)(auto ref U args) 111 if (__traits(compiles, opStar().opBinary!op(args))) 112 { 113 defaultInit(); 114 return opStar().opBinary!op(args); 115 } 116 117 void opIndexAssign(U, V)(auto const ref U arg1, auto const ref V arg2) 118 if (__traits(hasMember, typeof(opStar()), "opIndexAssign")) 119 { 120 defaultInit(); 121 opStar().opIndexAssign(arg1, arg2); 122 } 123 124 auto ref opIndex(U...)(U args) inout 125 if (__traits(hasMember, typeof(opStar()), "opIndex")) 126 { 127 return opStar().opIndex(args); 128 } 129 130 static if (__traits(compiles, opStar().opBinaryRight!("in")(ReturnType!(opStar().front).init))) 131 bool opBinaryRight(string op, U)(auto ref U e) const if (op == "in") 132 { 133 defaultInit(); 134 return opStar().opBinaryRight!("in")(e); 135 } 136 }