Differences From Artifact [cc1b586b87325960]:
- File
tricks/tricks.d
- 2010-11-23 09:36:27 - part of checkin [b97bd4f713] on branch trunk - automatic AST to table encoder (user: kinaba) [annotate]
To Artifact [00969146488cc3dc]:
- File
tricks/tricks.d
- 2010-11-24 17:44:58 - part of checkin [b993a8ad16] on branch trunk - auto memo and re-run feature of non @value/@macro layers re-re-re-implemented. (user: kinaba) [annotate]
95 // shiyo- desu. Don't use in this way. 95 // shiyo- desu. Don't use in this way.
96 // Tamp tries to call new Tomp(real) (because it only sees Tomp's memb 96 // Tamp tries to call new Tomp(real) (because it only sees Tomp's memb
97 // but it fails because Tomp takes (int,string,real). 97 // but it fails because Tomp takes (int,string,real).
98 assert( !__traits(compiles, { 98 assert( !__traits(compiles, {
99 class Tamp : Tomp { mixin SimpleConstructor; } 99 class Tamp : Tomp { mixin SimpleConstructor; }
100 }) ); 100 }) );
101 } 101 }
> 102
> 103 hash_t structuralHash(T)(T x)
> 104 {
> 105 alias SC_Unqual!(T) UCT;
> 106
> 107 static if(is(UCT == class))
> 108 return (cast(UCT)x).toHash();
> 109 else
> 110 static if(SC_HasGoodHash!(UCT))
> 111 { return typeid(UCT).getHash(&x); }
> 112 else
> 113 static if(is(UCT T == T[]))
> 114 { hash_t h; foreach(e; x) h+=structuralHash(e); return h; }
> 115 else
> 116 static if(is(UCT == struct))
> 117 static if(__traits(compiles, std.bigint.BigInt))
> 118 static if(is(UCT == std.bigint.BigInt))
> 119 return cast(hash_t) x.toInt();
> 120 else
> 121 static assert(false, "should not use struct.toHa
> 122 else
> 123 static assert(false, "should not use struct.toHash");
> 124 else
> 125 static assert(false, "nonhashable datatype "~UCT.stringof);
> 126 }
> 127
> 128 alias std.traits.Unqual SC_Unqual;
> 129
> 130 template SC_HasGoodHash(T)
> 131 {
> 132 enum SC_HasGoodHash =
> 133 is(T : bool) || isNumeric!(T) || isSomeString!(T) || isSomeChar!
> 134 }
102 135
103 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class 136 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class
> 137 /// BE SURE THAT THIS IS CONSISTENT WITH opCmp and opEquals
104 138
105 template SimpleToHash() 139 template SimpleToHash()
106 { 140 {
107 override hash_t toHash() const /// member-by-member hash 141 override hash_t toHash() const /// member-by-member hash
108 { 142 {
109 hash_t h = 0; 143 hash_t h = 0;
110 foreach(mem; this.tupleof) 144 foreach(mem; this.tupleof)
111 h += typeid(mem).getHash(&mem); | 145 h += structuralHash(mem);
112 return h; 146 return h;
113 } 147 }
114 } 148 }
> 149
> 150 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class
> 151
> 152 template SimpleCompareWithoutToHash()
> 153 {
> 154 override bool opEquals(Object rhs) const /// member-by-member equality
> 155 {
> 156 return opCmp(rhs) == 0;
> 157 }
> 158
> 159 override int opCmp(Object rhs_) const /// member-by-member compare
> 160 {
> 161 if( rhs_ is null )
> 162 return -1;
> 163 if( auto rhs = cast(typeof(this))rhs_ )
> 164 {
> 165 foreach(i,_; this.tupleof)
> 166 {
> 167 static if(is(typeof(_) == struct))
> 168 auto c = (cast(SC_Unqual!(typeof(_)))thi
> 169 else
> 170 auto c = typeid(_).compare(&this.tupleof
> 171 if(c)
> 172 return c;
> 173 }
> 174 return 0;
> 175 }
> 176 return typeid(this).opCmp(typeid(rhs_));
> 177 }
> 178 }
115 179
116 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class 180 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class
117 181
118 /*mixin*/ 182 /*mixin*/
119 template SimpleCompare() 183 template SimpleCompare()
120 { 184 {
121 override bool opEquals(Object rhs_) const /// member-by-member equality <
122 { <
123 if( auto rhs = cast(typeof(this))rhs_ ) <
124 { <
125 foreach(i,_; this.tupleof) <
126 if( this.tupleof[i] != (cast(const)rhs).tupleof[ <
127 return false; <
128 return true; <
129 } <
130 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), <
131 } <
132 <
133 mixin SimpleToHash; 185 mixin SimpleToHash;
134 <
135 override int opCmp(Object rhs_) const /// member-by-member compare <
136 { <
137 if( auto rhs = cast(typeof(this))rhs_ ) <
138 { <
139 foreach(i,_; this.tupleof) <
140 if( this.tupleof[i] != (cast(const)rhs).tupleof[ <
141 auto a = (cast(SC_Unqual!(typeof(this))) <
142 auto b = rhs.tupleof[i]; <
143 return a < b ? -1 : +1; <
144 } <
145 // not work well for structures??????? <
146 // if(auto c = typeid(_).compare(&this.tupleof[i],& <
147 // return c; <
148 return 0; <
149 } <
150 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), <
151 } <
> 186 mixin SimpleCompareWithoutToHash;
152 } 187 }
153 188
154 alias std.traits.Unqual SC_Unqual; <
155 <
156 unittest 189 unittest
157 { 190 {
158 class Temp 191 class Temp
159 { 192 {
160 int x; 193 int x;
161 string y; 194 string y;
162 mixin SimpleConstructor; 195 mixin SimpleConstructor;
................................................................................................................................................................................
173 class TempDummy 206 class TempDummy
174 { 207 {
175 int x; 208 int x;
176 string y; 209 string y;
177 mixin SimpleConstructor; 210 mixin SimpleConstructor;
178 mixin SimpleCompare; 211 mixin SimpleCompare;
179 } 212 }
180 assert_throw!AssertError( new Temp(1,"foo") == new TempDummy(1,"foo") ); | 213 assert_ne( new Temp(1,"foo"), new TempDummy(1,"foo") );
181 assert_throw!AssertError( new Temp(1,"foo") <= new TempDummy(1,"foo") ); | 214 assert_nothrow( new Temp(1,"foo") <= new TempDummy(1,"foo") );
182 } 215 }
183 216
184 /// Mixing-in a simple toString method 217 /// Mixing-in a simple toString method
185 218
186 /*mixin*/ 219 /*mixin*/
187 template SimpleToString() 220 template SimpleToString()
188 { 221 {
................................................................................................................................................................................
222 template SimpleClass() 255 template SimpleClass()
223 { 256 {
224 mixin SimpleConstructor; 257 mixin SimpleConstructor;
225 mixin SimpleCompare; 258 mixin SimpleCompare;
226 mixin SimpleToString; 259 mixin SimpleToString;
227 } 260 }
228 261
229 /// Will be used for dynamic overload resolution pattern | 262 /// Utility
230 263
231 template firstParam(T) 264 template firstParam(T)
232 { 265 {
233 alias ParameterTypeTuple!(T)[0] firstParam; 266 alias ParameterTypeTuple!(T)[0] firstParam;
234 } 267 }