diff options
Diffstat (limited to 'absl')
-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) { |