Use `AddConstRefIfExpensiveToCopy` and `ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS` for hash/eq functor members in SwissTable helpers.

HashElement, HashKey, and EqualElement previously stored `const Hash&` and `const KeyEqual&` references. Even for empty stateless functors (such as absl::Hash) or small trivially copyable stateful functors, those reference members occupied 8 bytes, forced callers like find_or_prepare_insert_small() to materialize and store `&this->hash_` on the stack inside HashKey, and placed HashKey::key at offset 8 instead of offset 0 in HashKey::GetHash().

Store hash/eq as `ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS type_traits_internal::AddConstRefIfExpensiveToCopy` so empty functors occupy no space and small trivial functors are passed and stored by value without pointer indirection.

PiperOrigin-RevId: 1009828336
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index 351fc22..4bb6fec 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -440,6 +440,7 @@
     ],
     deps = [
         "//absl/base:config",
+        "//absl/base:core_headers",
         "//absl/hash",
         "//absl/memory",
         "//absl/meta:type_traits",
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 5b33ebf..903b308 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -490,6 +490,7 @@
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::config
+    absl::core_headers
     absl::hash
     absl::memory
     absl::type_traits
diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h
index 065d97a..3d16a68 100644
--- a/absl/container/internal/container_memory.h
+++ b/absl/container/internal/container_memory.h
@@ -25,6 +25,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/hash/hash.h"
 #include "absl/memory/memory.h"
@@ -569,7 +570,9 @@
 // Useful for usage with policy traits.
 template <class Hash, bool kIsAbsl, size_t kSeedShift>
 struct HashElement {
-  HashElement(const Hash& h, size_t s) : hash(h), seed(s >> kSeedShift) {}
+  HashElement(type_traits_internal::AddConstRefIfExpensiveToCopy<Hash> h,
+              size_t s)
+      : hash(h), seed(s >> kSeedShift) {}
 
   template <class K, class... Args>
   size_t operator()(const K& key, Args&&...) const {
@@ -582,9 +585,8 @@
     // NOLINTNEXTLINE(clang-diagnostic-sign-conversion)
     return hash(key) ^ seed;
   }
-  // TODO(ezb): try using AddConstRefIfExpensiveToCopy and
-  // ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS for `hash`/`eq` functor members.
-  const Hash& hash;
+  ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS
+  type_traits_internal::AddConstRefIfExpensiveToCopy<Hash> hash;
   size_t seed;
 };
 
@@ -599,7 +601,8 @@
   static size_t GetHash(void* data, size_t seed) {
     return (*static_cast<const HashKey*>(data))(seed);
   }
-  const Hash& hash;
+  ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS
+  type_traits_internal::AddConstRefIfExpensiveToCopy<Hash> hash;
   type_traits_internal::AddConstRefIfExpensiveToCopy<Key> key;
 };
 
@@ -612,7 +615,8 @@
     ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(eq(lhs, rhs));
   }
   type_traits_internal::AddConstRefIfExpensiveToCopy<K1> rhs;
-  const KeyEqual& eq;
+  ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS
+  type_traits_internal::AddConstRefIfExpensiveToCopy<KeyEqual> eq;
 };
 
 // Type erased function for computing hash of the slot.
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index b31af8f..4c33b4f 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -4847,18 +4847,20 @@
 TEST(Table, AllocatorPropagation) { TestAllocPropagation<RawHashSetAlloc>(); }
 
 struct CountedHash {
+  explicit CountedHash(int* count) : count(count) {}
   size_t operator()(int64_t value) const {
-    ++count;
+    ++(*count);
     return static_cast<size_t>(value);
   }
-  mutable int count = 0;
+  int* count = nullptr;
 };
 
 struct CountedHashIntTable
     : raw_hash_set<IntPolicy, CountedHash, std::equal_to<int>,
                    std::allocator<int>> {
   using Base = typename CountedHashIntTable::raw_hash_set;
-  using Base::Base;
+  CountedHashIntTable() : Base(0, CountedHash(&count)) {}
+  int count = 0;
 };
 
 TEST(Table, CountedHash) {
@@ -4876,7 +4878,7 @@
   DisableSampling();
 
   using Table = CountedHashIntTable;
-  auto HashCount = [](const Table& t) { return t.hash_function().count; };
+  auto HashCount = [](const Table& t) { return t.count; };
   {
     Table t;
     t.find(0);