diff --git a/README.md b/README.md index a8262e9..7fc7610 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/parallel_hashmap/phmap.h b/parallel_hashmap/phmap.h index 12fcaf3..fce786d 100644 --- a/parallel_hashmap/phmap.h +++ b/parallel_hashmap/phmap.h @@ -47,9 +47,9 @@ #include #include +#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 @@ -4047,6 +4047,7 @@ struct HashEq : StringHashEqT {}; #endif // Supports heterogeneous lookup for pointers and smart pointers. +// ------------------------------------------------------------- template struct HashEq { @@ -4068,6 +4069,7 @@ struct HashEq private: static const T* ToPtr(const T* ptr) { return ptr; } + template static const T* ToPtr(const std::unique_ptr& ptr) { return ptr.get(); diff --git a/parallel_hashmap/phmap_fwd_decl.h b/parallel_hashmap/phmap_fwd_decl.h index a9fb514..69d18ab 100644 --- a/parallel_hashmap/phmap_fwd_decl.h +++ b/parallel_hashmap/phmap_fwd_decl.h @@ -14,9 +14,18 @@ #include #include +#if defined(PHMAP_USE_ABSL_HASH) + namespace absl { template struct Hash; }; +#endif + namespace phmap { +#if defined(PHMAP_USE_ABSL_HASH) + template using Hash = absl::Hash; +#else template struct Hash; +#endif + template struct EqualTo; template using Allocator = typename std::allocator; template using Pair = typename std::pair; @@ -29,13 +38,8 @@ namespace phmap { template struct HashEq { -#if defined(PHMAP_USE_ABSL_HASHEQ) - using Hash = absl::Hash; - using Eq = phmap::EqualTo; -#else using Hash = phmap::Hash; using Eq = phmap::EqualTo; -#endif }; template diff --git a/parallel_hashmap/phmap_utils.h b/parallel_hashmap/phmap_utils.h index ccc078c..5fe403e 100644 --- a/parallel_hashmap/phmap_utils.h +++ b/parallel_hashmap/phmap_utils.h @@ -23,6 +23,7 @@ #include #include +#include #include "phmap_bits.h" namespace phmap @@ -122,7 +123,11 @@ private: public: static constexpr bool value = std::is_same(0)), yes>::value; }; - + +#if defined(PHMAP_USE_ABSL_HASH) && !defined(phmap_fwd_decl_h_guard_) + namespace absl { template struct Hash; }; + template using Hash = absl::Hash; +#else // --------------------------------------------------------------- // phmap::Hash // --------------------------------------------------------------- @@ -264,6 +269,8 @@ struct Hash : public phmap_unary_function } }; +#endif + template struct Combiner { H operator()(H seed, size_t value); @@ -285,7 +292,7 @@ template struct Combiner } }; - +// define HashState to combine member hashes... see example below // ----------------------------------------------------------------------------- template class HashStateBase { @@ -301,11 +308,51 @@ template H HashStateBase::combine(H seed, const T& v, const Ts&... vs) { return HashStateBase::combine(Combiner()( - seed, phmap::Hash()(v)), vs...); + seed, phmap::Hash()(v)), + vs...); } using HashState = HashStateBase; +// ----------------------------------------------------------------------------- + +#if !defined(PHMAP_USE_ABSL_HASH) + +// define Hash for std::pair +// ------------------------- +template +struct Hash> { + size_t operator()(std::pair const& p) const noexcept { + return phmap::HashState().combine(0, p.first, p.second); + } +}; + +// define Hash for std::tuple +// -------------------------- +template +struct Hash> { + size_t operator()(std::tuple const& t) const noexcept { + return _hash_helper(t); + } + +private: + template + typename std::enable_if::type + _hash_helper(const std::tuple &) const noexcept { return 0; } + + template + typename std::enable_if::type + _hash_helper(const std::tuple &t) const noexcept { + const auto &el = std::get(t); + using el_type = std::remove_cv::type>::type; + return phmap::Hash()(el) + _hash_helper(t); + } +}; + + +#endif + + } // namespace phmap