
Dave Harris wrote:
and we now rely on the user overloads of hash_value to not produce a zero.
That's surely reasonable. The hash_value of any user-defined class should be defined in terms of the hash_values of primitives, and boost provides all of those.
I'm reluctant to elevate hash_combine and friends to a status of mandatory hash primitives. I think of them as utility components that help people write reasonable hash functions. As I said elsewhere, I think that it is reasonable for the only requirement on hash_value(x) to be that equivalent arguments yield the same result, and that distinct arguments "usually" produce different results. This is currently the case in TR1, too. So, in my opinion, your original suggestion is still the best one, even though I did not seem to agree at first. ;-)
Incidently, do you agree we will sometimes want to pass a hash value as the second argument to hash_combine? Like:
hash_combine( hash, hash_range( first, last ) ); hash_combine( hash, obj.get_hash( some_arg ) );
The first line should be hash_range( hash, first, last ); It's not the same thing, technically, but it has the same effect. The second should probably be hash_combine( hash, obj ); but...
If not, then maybe we should have a hash_combine that just combines hashes. At the moment the combining is mixed in with the getting; it's not a very orthogonal API.
... yes, hash_value( size_t ) is the identity function partly for this reason. The default in hash_combine is to invoke hash_value because these use cases outnumber the use cases where you already have a suitable size_t hash value.