Use `TypeErasedDerefAndApplyToSlotFn` in `NodeHashMapPolicy` and remove `TypeErasedDerefAndApplyToSlotFirstFn` In `NodeHashMapPolicy::get_hash_slot_fn()`, `pair::first` is at offset 0 of `value_type` when `IsLayoutCompatible<Key, Value>` holds, so `TypeErasedDerefAndApplyToSlotFn<Hash, Key, kIsAbsl, kSeedShift>` can be used directly instead of instantiating a separate `TypeErasedDerefAndApplyToSlotFirstFn<Hash, value_type, kIsAbsl, kSeedShift>` per mapped type `Value`. Delete the now-unused `TypeErasedDerefAndApplyToSlotFirstFn` from `container_memory.h`. PiperOrigin-RevId: 1009863244
diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h index 3d16a68..c9dd99d 100644 --- a/absl/container/internal/container_memory.h +++ b/absl/container/internal/container_memory.h
@@ -637,20 +637,17 @@ size_t TypeErasedDerefAndApplyToSlotFn(const void* fn, void* slot_ptr, size_t seed) { const auto* f = static_cast<const Fn*>(fn); - const T* slot = *static_cast<T**>(slot_ptr); + const T* slot; + // We use memcpy to avoid a strict-aliasing violation when this is called from + // NodeHashMapPolicy::get_hash_slot_fn(). In that case, slot_ptr has type + // `std::pair<const T, mapped_type>**`, which is not safe to dereference as + // `const T**`. Note that it is safe to dereference `slot` afterwards because + // `IsLayoutCompatible` guarantees that `std::pair<const T, mapped_type>` is + // standard-layout. + std::memcpy(&slot, slot_ptr, sizeof(slot)); return HashElement<Fn, kIsAbsl, kSeedShift>{*f, seed}(*slot); } -// Type erased function to apply `Fn` to data inside of the `slot_ptr->first`. -// The data is expected to have type `T`. -template <class Fn, class T, bool kIsAbsl, size_t kSeedShift> -size_t TypeErasedDerefAndApplyToSlotFirstFn(const void* fn, void* slot_ptr, - size_t seed) { - const auto* f = static_cast<const Fn*>(fn); - const T* slot = *static_cast<T**>(slot_ptr); - return HashElement<Fn, kIsAbsl, kSeedShift>{*f, seed}(slot->first); -} - } // namespace container_internal ABSL_NAMESPACE_END } // namespace absl
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h index 4a65ef5..28acb74 100644 --- a/absl/container/node_hash_map.h +++ b/absl/container/node_hash_map.h
@@ -685,8 +685,8 @@ template <class Hash, bool kIsAbsl, size_t kSeedShift> static constexpr HashSlotFn get_hash_slot_fn() { return memory_internal::IsLayoutCompatible<Key, Value>::value - ? &TypeErasedDerefAndApplyToSlotFirstFn<Hash, value_type, - kIsAbsl, kSeedShift> + ? &TypeErasedDerefAndApplyToSlotFn<Hash, Key, kIsAbsl, + kSeedShift> : nullptr; } };