Drake uses the hash_append pattern as described by N3980.
For a full treatment of the hash_append pattern, refer to: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3980.html
Providing hash_append support within a class
Drake types may implement a hash_append function. The function appends every hash-relevant member field into the hasher:
class MyValue {
public:
...
template <class HashAlgorithm>
friend void hash_append(
HashAlgorithm& hasher, const MyValue& item) noexcept {
hash_append(hasher, item.my_data_);
}
...
private:
std::string my_data_;
};
std::enable_if_t< std::is_integral_v< T > > hash_append(HashAlgorithm &hasher, const T &item) noexcept
Provides hash_append generic hashing for integral constants.
Definition hash.h:77
Checklist for reviewing a hash_append implementation:
- The function cites @ref hash_append in its Doxygen comment.
- The function is marked noexcept.
Using hashable types
Types that implement this pattern may be used in unordered collections:
std::unordered_set<MyValue, drake::DefaultHash> foo;
Some Drake types may also choose to specialize std::hash<MyValue> to use DefaultHash, so that the second template argument to std::unordered_set can be omitted. For example, Drake's symbolic::Expression header says:
}
Definition autodiff_overloads.h:161
drake::uhash< DefaultHasher > DefaultHash
The default hashing functor, akin to std::hash.
Definition hash.h:273
so that users are able to simply write:
std::unordered_set<drake::symbolic::Expression> foo;