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 95 // shiyo- desu. Don't use in this way.
96 96 // Tamp tries to call new Tomp(real) (because it only sees Tomp's members),
97 97 // but it fails because Tomp takes (int,string,real).
98 98 assert( !__traits(compiles, {
99 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.toHash");
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!(T) || isPointer!(T);
134 +}
102 135
103 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 139 template SimpleToHash()
106 140 {
107 141 override hash_t toHash() const /// member-by-member hash
108 142 {
109 143 hash_t h = 0;
110 144 foreach(mem; this.tupleof)
111 - h += typeid(mem).getHash(&mem);
145 + h += structuralHash(mem);
112 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(_)))this.tupleof[i]).opCmp(rhs.tupleof[i]);
169 + else
170 + auto c = typeid(_).compare(&this.tupleof[i],&rhs.tupleof[i]);
171 + if(c)
172 + return c;
173 + }
174 + return 0;
175 + }
176 + return typeid(this).opCmp(typeid(rhs_));
177 + }
178 +}
115 179
116 180 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class
117 181
118 182 /*mixin*/
119 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[i] )
127 - return false;
128 - return true;
129 - }
130 - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_)));
131 - }
132 -
133 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[i] ) {
141 - auto a = (cast(SC_Unqual!(typeof(this)))this).tupleof[i];
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],&rhs.tupleof[i]))
147 -// return c;
148 - return 0;
149 - }
150 - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_)));
151 - }
186 + mixin SimpleCompareWithoutToHash;
152 187 }
153 188
154 -alias std.traits.Unqual SC_Unqual;
155 -
156 189 unittest
157 190 {
158 191 class Temp
159 192 {
160 193 int x;
161 194 string y;
162 195 mixin SimpleConstructor;
................................................................................
173 206 class TempDummy
174 207 {
175 208 int x;
176 209 string y;
177 210 mixin SimpleConstructor;
178 211 mixin SimpleCompare;
179 212 }
180 - assert_throw!AssertError( new Temp(1,"foo") == new TempDummy(1,"foo") );
181 - assert_throw!AssertError( new Temp(1,"foo") <= new TempDummy(1,"foo") );
213 + assert_ne( new Temp(1,"foo"), new TempDummy(1,"foo") );
214 + assert_nothrow( new Temp(1,"foo") <= new TempDummy(1,"foo") );
182 215 }
183 216
184 217 /// Mixing-in a simple toString method
185 218
186 219 /*mixin*/
187 220 template SimpleToString()
188 221 {
................................................................................
222 255 template SimpleClass()
223 256 {
224 257 mixin SimpleConstructor;
225 258 mixin SimpleCompare;
226 259 mixin SimpleToString;
227 260 }
228 261
229 -/// Will be used for dynamic overload resolution pattern
262 +/// Utility
230 263
231 264 template firstParam(T)
232 265 {
233 266 alias ParameterTypeTuple!(T)[0] firstParam;
234 267 }