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 }