diff options
Diffstat (limited to 'absl/container/internal/hash_policy_traits.h')
-rw-r--r-- | absl/container/internal/hash_policy_traits.h | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/absl/container/internal/hash_policy_traits.h b/absl/container/internal/hash_policy_traits.h index 164ec123..86ffd1be 100644 --- a/absl/container/internal/hash_policy_traits.h +++ b/absl/container/internal/hash_policy_traits.h @@ -148,6 +148,41 @@ struct hash_policy_traits : common_policy_traits<Policy> { static auto value(T* elem) -> decltype(P::value(elem)) { return P::value(elem); } + + using HashSlotFn = size_t (*)(const void* hash_fn, void* slot); + + template <class Hash> + static constexpr HashSlotFn get_hash_slot_fn() { +// get_hash_slot_fn may return nullptr to signal that non type erased function +// should be used. GCC warns against comparing function address with nullptr. +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +// silent error: the address of * will never be NULL [-Werror=address] +#pragma GCC diagnostic ignored "-Waddress" +#endif + return Policy::template get_hash_slot_fn<Hash>() == nullptr + ? &hash_slot_fn_non_type_erased<Hash> + : Policy::template get_hash_slot_fn<Hash>(); +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + } + + private: + template <class Hash> + struct HashElement { + template <class K, class... Args> + size_t operator()(const K& key, Args&&...) const { + return h(key); + } + const Hash& h; + }; + + template <class Hash> + static size_t hash_slot_fn_non_type_erased(const void* hash_fn, void* slot) { + return Policy::apply(HashElement<Hash>{*static_cast<const Hash*>(hash_fn)}, + Policy::element(static_cast<slot_type*>(slot))); + } }; } // namespace container_internal |