summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2023-03-24 17:59:28 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2023-03-24 18:00:15 -0700
commitb6a1039bfcd6163b923c84e23e11439f42c98bc7 (patch)
treea698e397f0133c53da19616a8e29e5448a6b46b2
parent32e0395f3843479a2e74bdb48513b5a6a3e61287 (diff)
type_traits: provide a better fallback for is_trivially_relocatable.
We can do a lot better than always saying "no" on platforms without the __is_trivially_relocatable builtin. This will allow using this type trait from the move constructors of InlinedVector in a future CL, without needing to open code the fallback logic. PiperOrigin-RevId: 519281125 Change-Id: I0d55f019331966f58074850d6f77c7eab49f2c53
-rw-r--r--absl/meta/type_traits.h10
-rw-r--r--absl/meta/type_traits_test.cc17
2 files changed, 26 insertions, 1 deletions
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index 25462580..f713b78c 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -497,12 +497,20 @@ using swap_internal::StdSwapIsUnconstrained;
// https://clang.llvm.org/docs/LanguageExtensions.html#:~:text=__is_trivially_relocatable
//
#if ABSL_HAVE_BUILTIN(__is_trivially_relocatable)
+// If the compiler offers a builtin that tells us the answer, we can use that.
+// This covers all of the cases in the fallback below, plus types that opt in
+// using e.g. [[clang::trivial_abi]].
template <class T>
struct is_trivially_relocatable
: std::integral_constant<bool, __is_trivially_relocatable(T)> {};
#else
+// Otherwise we use a fallback that detects only those types we can feasibly
+// detect. Any time that has trivial move-construction and destruction
+// operations is by definition trivally relocatable.
template <class T>
-struct is_trivially_relocatable : std::integral_constant<bool, false> {};
+struct is_trivially_relocatable
+ : absl::conjunction<absl::is_trivially_move_constructible<T>,
+ absl::is_trivially_destructible<T>> {};
#endif
// absl::is_constant_evaluated()
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index 3e7cfbe7..d9e36887 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -743,6 +743,23 @@ TEST(TypeTraitsTest, IsNothrowSwappable) {
EXPECT_TRUE(IsNothrowSwappable<adl_namespace::SpecialNoexceptSwap>::value);
}
+TEST(TriviallyRelocatable, PrimitiveTypes) {
+ static_assert(absl::is_trivially_relocatable<int>::value, "");
+ static_assert(absl::is_trivially_relocatable<char>::value, "");
+ static_assert(absl::is_trivially_relocatable<void*>::value, "");
+}
+
+// User-defined types can be trivially relocatable as long as they don't have a
+// user-provided move constructor or destructor.
+TEST(TriviallyRelocatable, UserDefinedTriviallyReconstructible) {
+ struct S {
+ int x;
+ int y;
+ };
+
+ static_assert(absl::is_trivially_relocatable<S>::value, "");
+}
+
// A user-provided move constructor disqualifies a type from being trivially
// relocatable.
TEST(TriviallyRelocatable, UserProvidedMoveConstructor) {