From b6a1039bfcd6163b923c84e23e11439f42c98bc7 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 24 Mar 2023 17:59:28 -0700 Subject: 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 --- absl/meta/type_traits.h | 10 +++++++++- absl/meta/type_traits_test.cc | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'absl/meta') 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 struct is_trivially_relocatable : std::integral_constant {}; #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 -struct is_trivially_relocatable : std::integral_constant {}; +struct is_trivially_relocatable + : absl::conjunction, + absl::is_trivially_destructible> {}; #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::value); } +TEST(TriviallyRelocatable, PrimitiveTypes) { + static_assert(absl::is_trivially_relocatable::value, ""); + static_assert(absl::is_trivially_relocatable::value, ""); + static_assert(absl::is_trivially_relocatable::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::value, ""); +} + // A user-provided move constructor disqualifies a type from being trivially // relocatable. TEST(TriviallyRelocatable, UserProvidedMoveConstructor) { -- cgit v1.2.3