Move pass-by-value type traits to `absl::type_traits_internal`.

`ShouldSemanticallyPreferPassByValue` and `ShouldPreferPassByValue` are unchanged. `ShouldStructurallyPreferPassByValue` uses `(sizeof(T) & (sizeof(T) - 1)) == 0` in place of `absl::has_single_bit(sizeof(T))` to avoid a dependency from `type_traits` on `numeric:bits`.

PiperOrigin-RevId: 1004944315
diff --git a/absl/container/internal/raw_hash_map.h b/absl/container/internal/raw_hash_map.h
index 8984dfa..d4a7564 100644
--- a/absl/container/internal/raw_hash_map.h
+++ b/absl/container/internal/raw_hash_map.h
@@ -382,15 +382,17 @@
       // Try to avoid using std::tuple since that slows compilation.
       // (example: https://godbolt.org/z/nefW93T6K)
 
-      if constexpr (ShouldPreferPassByValue<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) {
+      if constexpr (type_traits_internal::ShouldPreferPassByValue<
+                        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) {
         // 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 0b2d03d..caf8219 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -2380,36 +2380,12 @@
                                               Alloc>::template rebind_alloc<T>>,
         T, void>>>;
 
-template <class T>
-using ShouldStructurallyPreferPassByValue = std::bool_constant<
-    // Check if size is a power of 2, to ensure cheap calls.
-    absl::has_single_bit(sizeof(T)) &&
-    // Check if copying 1-2 registers is enough. We don't want (for example) 32
-    // one-byte values to move around, since that sometimes results in poor
-    // codegen.
-    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 ShouldPreferPassByValue =
-    std::bool_constant<ShouldSemanticallyPreferPassByValue<T>::value &&
-                       ShouldStructurallyPreferPassByValue<std::conditional_t<
-                           std::is_void_v<T>, char, T>>::value>;
-
 // This is a 'struct' instead of 'using' in order to avoid eager evaluation for
 // callers that may be passing incomplete types.
 template <class T>
 struct AddConstRefIfExpensive
-    : std::conditional<ShouldPreferPassByValue<T>::value, T, const T&> {
+    : std::conditional<type_traits_internal::ShouldPreferPassByValue<T>::value,
+                       T, const T&> {
   static_assert(std::is_same_v<remove_cvref_t<T>, T>,
                 "passed types must be unqualified");
 };
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index b60579c..143d14e 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -635,6 +635,31 @@
                      IsOwner<absl::remove_cvref_t<U>>,
                      IsView<absl::remove_cvref_t<T>>>;
 
+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 &&
+    // Check if copying 1-2 registers is enough. We don't want (for example) 32
+    // one-byte values to move around, since that sometimes results in poor
+    // codegen.
+    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 ShouldPreferPassByValue =
+    std::bool_constant<ShouldSemanticallyPreferPassByValue<T>::value &&
+                       ShouldStructurallyPreferPassByValue<std::conditional_t<
+                           std::is_void_v<T>, char, T>>::value>;
+
 }  // namespace type_traits_internal
 
 ABSL_NAMESPACE_END
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index a11049c..ff44922 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -17,6 +17,7 @@
 #include <array>
 #include <cstdint>
 #include <functional>
+#include <memory>
 #include <string>
 #include <string_view>
 #include <tuple>
@@ -31,6 +32,9 @@
 #include "absl/time/clock.h"
 #include "absl/time/time.h"
 
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace type_traits_internal {
 namespace {
 
 using ::testing::StaticAssertTypeEq;
@@ -473,4 +477,40 @@
 #endif  // ABSL_HAVE_CONSTANT_EVALUATED
 }
 
+enum UnscopedEnum { kUnscoped };
+enum class ScopedEnum { kScoped };
+union TrivialUnion {
+  int a;
+  void* b;
+};
+struct TrivialMoveNonTrivialCopy {
+  TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {}  // NOLINT
+  TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default;
+};
+struct TrivialCopyNonTrivialMove {
+  TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default;
+  TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {}  // NOLINT
+};
+
+TEST(ShouldPreferPassByValue, Basic) {
+  static_assert(ShouldPreferPassByValue<int>::value);
+  static_assert(ShouldPreferPassByValue<void*>::value);
+  static_assert(ShouldPreferPassByValue<UnscopedEnum>::value);
+  static_assert(ShouldPreferPassByValue<ScopedEnum>::value);
+  static_assert(ShouldPreferPassByValue<TrivialUnion>::value);
+  static_assert(ShouldPreferPassByValue<std::string_view>::value);
+  static_assert(ShouldPreferPassByValue<std::pair<int, int>>::value);
+  static_assert(ShouldPreferPassByValue<std::pair<char, int>>::value);
+  static_assert(ShouldPreferPassByValue<TrivialMoveNonTrivialCopy>::value);
+  static_assert(!ShouldPreferPassByValue<TrivialCopyNonTrivialMove>::value);
+  static_assert(!ShouldPreferPassByValue<void>::value);
+  static_assert(!ShouldPreferPassByValue<char[3]>::value);
+  static_assert(!ShouldPreferPassByValue<char[4]>::value);
+  static_assert(!ShouldPreferPassByValue<std::string>::value);
+  static_assert(!ShouldPreferPassByValue<std::shared_ptr<int>>::value);
+}
+
 }  // namespace
+}  // namespace type_traits_internal
+ABSL_NAMESPACE_END
+}  // namespace absl