diff options
author | Abseil Team <absl-team@google.com> | 2023-03-24 17:59:28 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-03-24 18:00:15 -0700 |
commit | b6a1039bfcd6163b923c84e23e11439f42c98bc7 (patch) | |
tree | a698e397f0133c53da19616a8e29e5448a6b46b2 | |
parent | 32e0395f3843479a2e74bdb48513b5a6a3e61287 (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.h | 10 | ||||
-rw-r--r-- | absl/meta/type_traits_test.cc | 17 |
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) { |