summaryrefslogtreecommitdiff
path: root/absl/meta
diff options
context:
space:
mode:
Diffstat (limited to 'absl/meta')
-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) {