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