Phobos2: sorting and std.typecons.Tuple
bearophile
bearophileHUGS at lycos.com
Mon Apr 27 15:11:16 PDT 2009
Christopher Wright:
> bearophile explicitly said "structs". I assume it would extend to
> primitives, treating pointers as integer types. I also assume it would
> call .toHash on any object.
If you are interested this is the code:
/**********************************************
Return the standard hash value of the given value/object.
It uses the toHash() method of the given object/struct if it's defined.
If 'value' is a struct that doesn't define a toHash(), then it returns a
combination of hash() mapped on each of its fields, so it computes a correct
hash value of structs that contain dynamic arrays too. So it's used inside
the Record struct like this:
-------------
uint toHash() {
return hash(*this, true);
}
-------------
You can use the same in your structs to avoid that problem with dynamic
array fields.
The 'inside_struct' run-time boolean flag is necessary to avoid infinite recursion
when you define a toHash() using a hash(): set it to true in that situation, and
leave its default false value in all other situations.
*/
hash_t hash(T)(T value, bool inside_struct=false) {
if (inside_struct) {
static if ( is(T == struct) ) {
// adapted from [...]
// This to hash (hopefully) correctly structs that contain arrays!
uint mult = 1000003;
uint result = 0x345678; // I haven't used a hash_t here
foreach (i, el; value.tupleof) { // this is a static foreach
result = (result ^ hash(el)) * mult; // recursive call
mult += 82520 + i + i;
}
return result + 97531;
} else static if ( is(typeof(T.toHash)) || is(typeof(T.init.toHash)) ) {
return value.toHash();
} else {
// Suggested by "John C" <johnch_atms hotmail.com>
return typeid(T).getHash(&value);
}
} else {
static if ( is(typeof(T.toHash)) || is(typeof(T.init.toHash)) ) {
return value.toHash();
} else static if ( is(T == struct) ) {
// adapted from [...]
// This to hash (hopefully) correctly structs that contain arrays!
uint mult = 1000003;
uint result = 0x345678;
foreach (i, el; value.tupleof) { // this is a static foreach
result = (result ^ hash(el)) * mult; // recursive call
mult += 82520 + i + i;
}
return result + 97531;
} else {
// Suggested by "John C" <johnch_atms hotmail.com>
return typeid(T).getHash(&value);
}
}
}
I didn't find a way to use a compile-time inside_struct flag.
Bye,
bearophile
More information about the Digitalmars-d
mailing list