Add default hash for std::pair and std::tuple... slight code reorganization.

This commit is contained in:
greg
2019-11-03 13:42:47 -05:00
parent 54665f80f4
commit 1de1a98cbd
4 changed files with 63 additions and 10 deletions
Vendored
+1 -1
View File
@@ -107,7 +107,7 @@ The full types with template parameters can be found in the [parallel_hashmap/ph
## Changes to Abseil's hashmaps
- The default hash framework is std::hash, not absl::Hash. However, if you prefer the default to be the Abseil hash framework, include the Abseil headers before `phmap.h` and define the preprocessor macro `PHMAP_USE_ABSL_HASHEQ`.
- The default hash framework is std::hash, not absl::Hash. However, if you prefer the default to be the Abseil hash framework, include the Abseil headers before `phmap.h` and define the preprocessor macro `PHMAP_USE_ABSL_HASH`.
- The `erase(iterator)` and `erase(const_iterator)` both return an iterator to the element following the removed element, as does the std::unordered_map. A non-standard `void _erase(iterator)` is provided in case the return value is not needed.
+3 -1
View File
@@ -47,9 +47,9 @@
#include <cassert>
#include <atomic>
#include "phmap_fwd_decl.h"
#include "phmap_utils.h"
#include "phmap_base.h"
#include "phmap_fwd_decl.h"
#if PHMAP_HAVE_STD_STRING_VIEW
#include <string_view>
@@ -4047,6 +4047,7 @@ struct HashEq<std::wstring_view> : StringHashEqT<wchar_t> {};
#endif
// Supports heterogeneous lookup for pointers and smart pointers.
// -------------------------------------------------------------
template <class T>
struct HashEq<T*>
{
@@ -4068,6 +4069,7 @@ struct HashEq<T*>
private:
static const T* ToPtr(const T* ptr) { return ptr; }
template <class U, class D>
static const T* ToPtr(const std::unique_ptr<U, D>& ptr) {
return ptr.get();
+9 -5
View File
@@ -14,9 +14,18 @@
#include <memory>
#include <utility>
#if defined(PHMAP_USE_ABSL_HASH)
namespace absl { template <class T> struct Hash; };
#endif
namespace phmap {
#if defined(PHMAP_USE_ABSL_HASH)
template <class T> using Hash = absl::Hash<T>;
#else
template <class T> struct Hash;
#endif
template <class T> struct EqualTo;
template <class T> using Allocator = typename std::allocator<T>;
template<class T1, class T2> using Pair = typename std::pair<T1, T2>;
@@ -29,13 +38,8 @@ namespace phmap {
template <class T, class E = void>
struct HashEq
{
#if defined(PHMAP_USE_ABSL_HASHEQ)
using Hash = absl::Hash<T>;
using Eq = phmap::EqualTo<T>;
#else
using Hash = phmap::Hash<T>;
using Eq = phmap::EqualTo<T>;
#endif
};
template <class T>
+49 -2
View File
@@ -23,6 +23,7 @@
#include <cstdint>
#include <functional>
#include <tuple>
#include "phmap_bits.h"
namespace phmap
@@ -123,6 +124,10 @@ public:
static constexpr bool value = std::is_same<decltype(test<T>(0)), yes>::value;
};
#if defined(PHMAP_USE_ABSL_HASH) && !defined(phmap_fwd_decl_h_guard_)
namespace absl { template <class T> struct Hash; };
template <class T> using Hash = absl::Hash<T>;
#else
// ---------------------------------------------------------------
// phmap::Hash
// ---------------------------------------------------------------
@@ -264,6 +269,8 @@ struct Hash<double> : public phmap_unary_function<double, size_t>
}
};
#endif
template <class H, int sz> struct Combiner
{
H operator()(H seed, size_t value);
@@ -285,7 +292,7 @@ template <class H> struct Combiner<H, 8>
}
};
// define HashState to combine member hashes... see example below
// -----------------------------------------------------------------------------
template <typename H>
class HashStateBase {
@@ -301,11 +308,51 @@ template <typename T, typename... Ts>
H HashStateBase<H>::combine(H seed, const T& v, const Ts&... vs)
{
return HashStateBase<H>::combine(Combiner<H, sizeof(H)>()(
seed, phmap::Hash<T>()(v)), vs...);
seed, phmap::Hash<T>()(v)),
vs...);
}
using HashState = HashStateBase<size_t>;
// -----------------------------------------------------------------------------
#if !defined(PHMAP_USE_ABSL_HASH)
// define Hash for std::pair
// -------------------------
template<class T1, class T2>
struct Hash<std::pair<T1, T2>> {
size_t operator()(std::pair<T1, T2> const& p) const noexcept {
return phmap::HashState().combine(0, p.first, p.second);
}
};
// define Hash for std::tuple
// --------------------------
template<class... T>
struct Hash<std::tuple<T...>> {
size_t operator()(std::tuple<T...> const& t) const noexcept {
return _hash_helper(t);
}
private:
template<size_t I = 0, class ...P>
typename std::enable_if<I == sizeof...(P), size_t>::type
_hash_helper(const std::tuple<P...> &) const noexcept { return 0; }
template<size_t I = 0, class ...P>
typename std::enable_if<I < sizeof...(P), size_t>::type
_hash_helper(const std::tuple<P...> &t) const noexcept {
const auto &el = std::get<I>(t);
using el_type = std::remove_cv<std::remove_reference<decltype(el)>::type>::type;
return phmap::Hash<el_type>()(el) + _hash_helper<I + 1>(t);
}
};
#endif
} // namespace phmap