Make PolicyTraits::transfer_uses_memcpy() true for node_hash_* tables.

This should enable binary size savings for now and more efficiency improvements with small buffer optimization.

PiperOrigin-RevId: 564741270
Change-Id: Icf204d88256243eb60464439a52dd589d7a559cb
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index 208e78e..5131837 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -499,6 +499,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":common_policy_traits",
+        "//absl/base:config",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -582,6 +583,7 @@
     deps = [
         ":hash_policy_traits",
         ":node_slot_policy",
+        "//absl/base:config",
         "@com_google_googletest//:gtest_main",
     ],
 )
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 64f6965..f5ef0dd 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -577,6 +577,7 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::common_policy_traits
+    absl::config
     GTest::gmock_main
 )
 
@@ -660,6 +661,7 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::config
     absl::hash_policy_traits
     absl::node_slot_policy
     GTest::gmock_main
diff --git a/absl/container/internal/common_policy_traits.h b/absl/container/internal/common_policy_traits.h
index 3558a54..57eac67 100644
--- a/absl/container/internal/common_policy_traits.h
+++ b/absl/container/internal/common_policy_traits.h
@@ -93,11 +93,13 @@
   struct Rank0 : Rank1 {};
 
   // Use auto -> decltype as an enabler.
+  // P::transfer returns std::true_type if transfer uses memcpy (e.g. in
+  // node_slot_policy).
   template <class Alloc, class P = Policy>
   static auto transfer_impl(Alloc* alloc, slot_type* new_slot,
                             slot_type* old_slot, Rank0)
-      -> decltype((void)P::transfer(alloc, new_slot, old_slot)) {
-    P::transfer(alloc, new_slot, old_slot);
+      -> decltype(P::transfer(alloc, new_slot, old_slot)) {
+    return P::transfer(alloc, new_slot, old_slot);
   }
 #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
   // This overload returns true_type for the trait below.
diff --git a/absl/container/internal/common_policy_traits_test.cc b/absl/container/internal/common_policy_traits_test.cc
index 5eaa4aa..faee3e7 100644
--- a/absl/container/internal/common_policy_traits_test.cc
+++ b/absl/container/internal/common_policy_traits_test.cc
@@ -16,10 +16,12 @@
 
 #include <functional>
 #include <memory>
-#include <new>
+#include <type_traits>
+#include <utility>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -51,9 +53,14 @@
 struct PolicyWithOptionalOps : PolicyWithoutOptionalOps {
   static std::function<void(void*, Slot*, Slot*)> transfer;
 };
-
 std::function<void(void*, Slot*, Slot*)> PolicyWithOptionalOps::transfer;
 
+struct PolicyWithMemcpyTransfer : PolicyWithoutOptionalOps {
+  static std::function<std::true_type(void*, Slot*, Slot*)> transfer;
+};
+std::function<std::true_type(void*, Slot*, Slot*)>
+    PolicyWithMemcpyTransfer::transfer;
+
 struct Test : ::testing::Test {
   Test() {
     PolicyWithoutOptionalOps::construct = [&](void* a1, Slot* a2, Slot a3) {
@@ -114,6 +121,13 @@
   common_policy_traits<PolicyWithOptionalOps>::transfer(&alloc, &a, &b);
 }
 
+TEST(TransferUsesMemcpy, Basic) {
+  EXPECT_FALSE(
+      common_policy_traits<PolicyWithOptionalOps>::transfer_uses_memcpy());
+  EXPECT_TRUE(
+      common_policy_traits<PolicyWithMemcpyTransfer>::transfer_uses_memcpy());
+}
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/absl/container/internal/node_slot_policy.h b/absl/container/internal/node_slot_policy.h
index baba574..3f1874d 100644
--- a/absl/container/internal/node_slot_policy.h
+++ b/absl/container/internal/node_slot_policy.h
@@ -62,9 +62,12 @@
     Policy::delete_element(alloc, *slot);
   }
 
+  // Returns true_type to indicate that transfer can use memcpy.
   template <class Alloc>
-  static void transfer(Alloc*, slot_type* new_slot, slot_type* old_slot) {
+  static std::true_type transfer(Alloc*, slot_type* new_slot,
+                                 slot_type* old_slot) {
     *new_slot = *old_slot;
+    return {};
   }
 
   static size_t space_used(const slot_type* slot) {
diff --git a/absl/container/internal/node_slot_policy_test.cc b/absl/container/internal/node_slot_policy_test.cc
index 51b7467..d4ea919 100644
--- a/absl/container/internal/node_slot_policy_test.cc
+++ b/absl/container/internal/node_slot_policy_test.cc
@@ -18,6 +18,7 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
 #include "absl/container/internal/hash_policy_traits.h"
 
 namespace absl {
@@ -61,6 +62,7 @@
   int* b = &s;
   NodePolicy::transfer(&alloc, &a, &b);
   EXPECT_EQ(&s, a);
+  EXPECT_TRUE(NodePolicy::transfer_uses_memcpy());
 }
 
 }  // namespace