Diff
Not logged in

Differences From Artifact [cc1b586b87325960]:

To Artifact [00969146488cc3dc]:


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 }