Chromium Code Reviews| Index: mojo/public/cpp/bindings/lib/clone_equals_util.h |
| diff --git a/mojo/public/cpp/bindings/lib/clone_equals_util.h b/mojo/public/cpp/bindings/lib/clone_equals_util.h |
| index f7bd898c3001c4e8e086d4e8408411061ad9248b..45fe94c953dc1329eccc76103e37d2fe7d9e3e7d 100644 |
| --- a/mojo/public/cpp/bindings/lib/clone_equals_util.h |
| +++ b/mojo/public/cpp/bindings/lib/clone_equals_util.h |
| @@ -5,6 +5,7 @@ |
| #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_CLONE_EQUALS_UTIL_H_ |
| #define MOJO_PUBLIC_CPP_BINDINGS_LIB_CLONE_EQUALS_UTIL_H_ |
| +#include <functional> |
| #include <type_traits> |
| #include <unordered_map> |
| #include <vector> |
| @@ -155,6 +156,76 @@ bool Equals(const T& a, const T& b) { |
| return EqualsTraits<T>::Equals(a, b); |
| } |
| +template <typename T> |
| +size_t HashCombine(size_t seed, const T& value) { |
|
yzshen1
2016/09/20 23:44:39
Does it make sense to move hash-related functions
tibell
2016/09/21 07:10:53
Done.
|
| + // Based on proposal in: |
| + // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf |
| + return seed ^ (std::hash<T>()(value) + (seed << 6) + (seed >> 2)); |
| +} |
| + |
| +template <typename T> |
| +struct HasHashMethod { |
| + template <typename U> |
| + static char Test(decltype(&U::Hash)); |
| + template <typename U> |
| + static int Test(...); |
| + static const bool value = sizeof(Test<T>(0)) == sizeof(char); |
| + |
| + private: |
| + EnsureTypeIsComplete<T> check_t_; |
| +}; |
| + |
| +template <typename T, bool has_hash_method = HasHashMethod<T>::value> |
| +struct HashTraits; |
| + |
| +template <typename T> |
| +size_t Hash(size_t seed, const T& value); |
| + |
| +template <typename T> |
| +struct HashTraits<T, true> { |
| + static size_t Hash(size_t seed, const T& value) { return value.Hash(seed); } |
| +}; |
| + |
| +template <typename T> |
| +struct HashTraits<T, false> { |
| + static size_t Hash(size_t seed, const T& value) { |
| + return HashCombine(seed, value); |
| + } |
| +}; |
| + |
| +template <typename T> |
| +struct HashTraits<base::Optional<T>, false> { |
|
Sam McNally
2016/09/21 04:57:58
If we're still disallowing nullable structs, array
tibell
2016/09/21 07:10:53
Done. Deleted.
|
| + static size_t Hash(size_t seed, const base::Optional<T>& value) { |
| + return !value ? HashCombine(seed, 0) : internal::Hash(seed, *value); |
|
yzshen1
2016/09/20 23:44:39
nit: is "internal::" necessary here?
tibell
2016/09/21 07:10:53
Done.
|
| + } |
| +}; |
| + |
| +template <typename T> |
| +struct HashTraits<std::vector<T>, false> { |
| + static size_t Hash(size_t seed, const std::vector<T>& value) { |
| + for (const auto& element : value) { |
| + seed = Hash(seed, element); |
| + } |
| + return seed; |
| + } |
| +}; |
| + |
| +template <typename K, typename V> |
| +struct HashTraits<std::unordered_map<K, V>, false> { |
| + static size_t Hash(size_t seed, const std::unordered_map<K, V>& value) { |
| + for (const auto& element : value) { |
| + seed = Hash(seed, element.first); |
| + seed = Hash(seed, element.second); |
| + } |
| + return seed; |
| + } |
| +}; |
| + |
| +template <typename T> |
| +size_t Hash(size_t seed, const T& value) { |
| + return HashTraits<T>::Hash(seed, value); |
| +} |
| + |
| } // namespace internal |
| } // namespace mojo |