Move kIsMoveSameAsCopy and IsAllocMoveSameAsCopy to absl/meta/type_traits.h and factor out IsDefaultAlloc logic

PiperOrigin-RevId: 1008270403
diff --git a/absl/container/internal/raw_hash_map.h b/absl/container/internal/raw_hash_map.h
index 3495905..645b447 100644
--- a/absl/container/internal/raw_hash_map.h
+++ b/absl/container/internal/raw_hash_map.h
@@ -84,8 +84,8 @@
   // separate move-only overloads.
   template <class K, bool Value, bool ExtraConstraint = true>
   using LifetimeBoundK = std::bool_constant<
-      (ExtraConstraint ||
-       !IsAllocMoveSameAsCopy<absl::remove_cvref_t<K>, Alloc>::value) &&
+      (ExtraConstraint || !type_traits_internal::IsAllocMoveSameAsCopy<
+                              absl::remove_cvref_t<K>, Alloc>::value) &&
       HasValue<Value, std::conditional_t<
                           policy_trait_element_is_owner<Policy>::value,
                           std::false_type,
@@ -383,16 +383,13 @@
       // (example: https://godbolt.org/z/nefW93T6K)
 
       if constexpr (type_traits_internal::ShouldPreferPassByValueOverRRef<
-                        std::conditional_t<
-                            sizeof...(Args) == 0 &&
-                                std::is_same_v<
-                                    typename std::allocator_traits<
-                                        Alloc>::template rebind_alloc<char>,
-                                    std::allocator<char>>,
-                            mapped_type,
-                            // Trick to avoid unnecessary template
-                            // instantiations.
-                            void>>::value) {
+                        std::conditional_t<sizeof...(Args) == 0 &&
+                                               type_traits_internal::
+                                                   IsDefaultAlloc<Alloc>::value,
+                                           mapped_type,
+                                           // Trick to avoid unnecessary
+                                           // template instantiations.
+                                           void>>::value) {
         // Common case: operator[]
         // Note: This has a different run-time performance characteristic than
         // the other branches, due to the usage of a temporary object. In the
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 8f07678..7a18275 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -2355,55 +2355,6 @@
       TypeList<Policy, Hash, Eq, Alloc>>::type;
 };
 
-template <class T>
-using HasTrivialCopyAndMove =
-    std::bool_constant<std::is_trivially_copy_constructible_v<T> &&
-                       std::is_trivially_move_constructible_v<T>>;
-
-// In principle, being trivially copy- and move-constructible is sufficient
-// (though not necessary) for proving copy and move equivalence. However, we
-// can't even test that for all types, because not all types are complete at the
-// point of evaluation of this trait. Therefore, we restrict this trait to a
-// subset of common types that we know to be complete at the point of evaluation
-// of this trait.
-template <class T>
-inline constexpr bool kIsMoveSameAsCopy = HasTrivialCopyAndMove<
-    std::conditional_t<(!std::is_class_v<T> && !std::is_union_v<T>) ||
-                           std::is_same_v<T, std::type_index> ||
-                           std::is_same_v<T, absl::string_view>,
-                       T, void>>::value;
-
-template <class T, class Traits>
-inline constexpr bool kIsMoveSameAsCopy<std::basic_string_view<T, Traits>> =
-    std::is_trivially_copy_constructible_v<std::basic_string_view<T, Traits>>;
-
-template <class T, size_t N>
-inline constexpr bool kIsMoveSameAsCopy<std::array<T, N>> =
-    kIsMoveSameAsCopy<T>;
-
-template <class T>
-inline constexpr bool kIsMoveSameAsCopy<std::optional<T>> =
-    kIsMoveSameAsCopy<T>;
-
-template <class T1, class T2>
-inline constexpr bool kIsMoveSameAsCopy<std::pair<T1, T2>> =
-    kIsMoveSameAsCopy<T1> && kIsMoveSameAsCopy<T2>;
-
-template <class... T>
-inline constexpr bool kIsMoveSameAsCopy<std::tuple<T...>> =
-    (true && ... && kIsMoveSameAsCopy<T>);
-
-template <class... T>
-inline constexpr bool kIsMoveSameAsCopy<std::variant<T...>> =
-    (true && ... && kIsMoveSameAsCopy<T>);
-
-template <class T, class Alloc = std::allocator<T>>
-using IsAllocMoveSameAsCopy =
-    std::bool_constant<kIsMoveSameAsCopy<std::conditional_t<
-        std::is_same_v<std::allocator<T>, typename std::allocator_traits<
-                                              Alloc>::template rebind_alloc<T>>,
-        T, void>>>;
-
 // This is a 'struct' instead of 'using' in order to avoid eager evaluation for
 // callers that may be passing incomplete types.
 template <class T>
@@ -2416,10 +2367,9 @@
 };
 
 template <class T, class Alloc = std::allocator<T>>
-using PreferredMoveParamType =
-    typename std::conditional_t<IsAllocMoveSameAsCopy<T, Alloc>::value,
-                                AddConstRefIfExpensive<T>,
-                                std::add_rvalue_reference<T>>::type;
+using PreferredMoveParamType = typename std::conditional_t<
+    type_traits_internal::IsAllocMoveSameAsCopy<T, Alloc>::value,
+    AddConstRefIfExpensive<T>, std::add_rvalue_reference<T>>::type;
 
 // A SwissTable.
 //
@@ -2587,9 +2537,9 @@
   // Bit-fields cannot be moved, and types with trivial copy and move
   // constructors should also not be moved.
   template <class T>
-  using EnableElementMoveFrom =
-      std::bool_constant<std::is_pointer_v<T*> &&
-                         !IsAllocMoveSameAsCopy<T, Alloc>::value>;
+  using EnableElementMoveFrom = std::bool_constant<
+      std::is_pointer_v<T*> &&
+      !type_traits_internal::IsAllocMoveSameAsCopy<T, Alloc>::value>;
 
   // RequiresNotInit is a workaround for gcc prior to 7.1.
   // See https://godbolt.org/g/Y4xsUh.
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index 51dfb27..4738693 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -35,13 +35,18 @@
 #ifndef ABSL_META_TYPE_TRAITS_H_
 #define ABSL_META_TYPE_TRAITS_H_
 
+#include <limits.h>
+
 #include <array>
 #include <cstddef>
 #include <functional>
+#include <memory>
+#include <optional>
 #include <string>
 #include <string_view>
 #include <tuple>
 #include <type_traits>
+#include <typeindex>
 #include <utility>
 #include <variant>
 #include <vector>
@@ -66,6 +71,10 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
+#ifndef ABSL_USES_STD_STRING_VIEW
+class string_view;
+#endif
+
 namespace type_traits_internal {
 
 template <typename... Ts>
@@ -636,6 +645,66 @@
                      IsView<absl::remove_cvref_t<T>>>;
 
 template <class T>
+using HasTrivialCopyAndMove =
+    std::bool_constant<std::is_trivially_copy_constructible_v<T> &&
+                       std::is_trivially_move_constructible_v<T>>;
+
+// In principle, being trivially copy- and move-constructible is sufficient
+// (though not necessary) for proving copy and move equivalence. However, we
+// can't even test that for all types, because not all types are complete at the
+// point of evaluation of this trait. Therefore, we restrict this trait to a
+// subset of common types that we know to be complete at the point of evaluation
+// of this trait.
+template <class T>
+inline constexpr bool kIsMoveSameAsCopy =
+    HasTrivialCopyAndMove<std::conditional_t<
+        std::is_class_v<T> || std::is_union_v<T>, void, T>>::value;
+
+template <class T, class Traits>
+inline constexpr bool kIsMoveSameAsCopy<std::basic_string_view<T, Traits>> =
+    std::is_trivially_copy_constructible_v<std::basic_string_view<T, Traits>>;
+
+template <class T, size_t N>
+inline constexpr bool kIsMoveSameAsCopy<std::array<T, N>> =
+    kIsMoveSameAsCopy<T>;
+
+template <class T>
+inline constexpr bool kIsMoveSameAsCopy<std::optional<T>> =
+    kIsMoveSameAsCopy<T>;
+
+template <class T1, class T2>
+inline constexpr bool kIsMoveSameAsCopy<std::pair<T1, T2>> =
+    kIsMoveSameAsCopy<T1> && kIsMoveSameAsCopy<T2>;
+
+template <class... T>
+inline constexpr bool kIsMoveSameAsCopy<std::tuple<T...>> =
+    (true && ... && kIsMoveSameAsCopy<T>);
+
+template <>
+inline constexpr bool kIsMoveSameAsCopy<std::type_index> = true;
+
+template <class... T>
+inline constexpr bool kIsMoveSameAsCopy<std::variant<T...>> =
+    (true && ... && kIsMoveSameAsCopy<T>);
+
+#ifndef ABSL_USES_STD_STRING_VIEW
+template <>
+inline constexpr bool kIsMoveSameAsCopy<absl::string_view> =
+    kIsMoveSameAsCopy<std::string_view>;
+#endif
+
+template <class Alloc>
+using IsDefaultAlloc = std::is_same<
+    std::allocator<typename std::allocator_traits<Alloc>::value_type>,
+    typename std::allocator_traits<Alloc>::template rebind_alloc<
+        typename std::allocator_traits<Alloc>::value_type>>;
+
+template <class T, class Alloc = std::allocator<T>>
+using IsAllocMoveSameAsCopy =
+    std::bool_constant<type_traits_internal::kIsMoveSameAsCopy<
+        std::conditional_t<IsDefaultAlloc<Alloc>::value, T, void>>>;
+
+template <class T>
 using ShouldStructurallyPreferPassByValue = std::bool_constant<
     // Check if size is a power of 2, to ensure cheap calls.
     (sizeof(T) & (sizeof(T) - 1)) == 0 &&
@@ -645,20 +714,15 @@
     alignof(T) * 2 >= sizeof(T) &&
     sizeof(T) <= sizeof(std::pair<void*, size_t>)>;
 
-template <class T>
-using ShouldSemanticallyPreferPassByValue =
-    std::bool_constant<std::is_trivially_move_constructible_v<T> &&
-                       std::is_trivially_destructible_v<T>>;
-
 // Checks the given type to see if it is a good candidate for accepting by value
 // instead of by rvalue-reference. This includes both a semantic constraint
 // (to ensure correctness), as well as a structural constraint (to ensure
 // performance).
 template <class T>
-using ShouldPreferPassByValueOverRRef =
-    std::bool_constant<ShouldSemanticallyPreferPassByValue<T>::value &&
-                       ShouldStructurallyPreferPassByValue<std::conditional_t<
-                           std::is_void_v<T>, char, T>>::value>;
+using ShouldPreferPassByValueOverRRef = ShouldStructurallyPreferPassByValue<
+    std::conditional_t<std::is_trivially_move_constructible_v<T> &&
+                           std::is_trivially_destructible_v<T>,
+                       T, char[SHRT_MAX]>>;
 
 }  // namespace type_traits_internal