Change the macro ABSL_IS_TRIVIALLY_RELOCATABLE into a type trait - absl::is_trivially_relocatable - and move it from optimization.h to type_traits.h.

Example of how to change to the new type trait:
```
#include "absl/base/attributes.h"

if (ABSL_IS_TRIVIALLY_RELOCATABLE(T)) { DoSomething(); }
```
to
```
#include "absl/meta/type_traits.h"

if (absl::is_trivially_relocatable<T>::value) { DoSomething(); }
```

Note that optimization.h is also built in C mode so we can't put a type trait there.

PiperOrigin-RevId: 475633715
Change-Id: I2bc85f3f6711d1280049fd01eb97c497d2d0d929
pull/1283/head
Evan Brown 2 years ago committed by Copybara-Service
parent 800c04f64a
commit d859fafe1a
  1. 24
      absl/base/optimization.h
  2. 19
      absl/base/optimization_test.cc
  3. 1
      absl/meta/BUILD.bazel
  4. 1
      absl/meta/CMakeLists.txt
  5. 28
      absl/meta/type_traits.h
  6. 19
      absl/meta/type_traits_test.cc

@ -249,28 +249,4 @@
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME()
#endif
// ABSL_IS_TRIVIALLY_RELOCATABLE(type)
// Detects whether a type is "trivially relocatable" -- meaning it can be
// relocated without invoking the constructor/destructor, using a form of move
// elision.
//
// Example:
//
// if constexpr (ABSL_IS_TRIVIALLY_RELOCATABLE(T)) {
// memcpy(new_location, old_location, sizeof(T));
// } else {
// new(new_location) T(std::move(*old_location));
// old_location->~T();
// }
//
// Upstream documentation:
//
// https://clang.llvm.org/docs/LanguageExtensions.html#:~:text=__is_trivially_relocatable
//
#if ABSL_HAVE_BUILTIN(__is_trivially_relocatable)
#define ABSL_IS_TRIVIALLY_RELOCATABLE(type) __is_trivially_relocatable(type)
#else
#define ABSL_IS_TRIVIALLY_RELOCATABLE(type) false
#endif
#endif // ABSL_BASE_OPTIMIZATION_H_

@ -15,7 +15,6 @@
#include "absl/base/optimization.h"
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/types/optional.h"
namespace {
@ -127,22 +126,4 @@ TEST(PredictTest, ExplicitBoolConversion) {
if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
}
TEST(TrivallyRelocatable, Sanity) {
#if !defined(ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI) || \
!ABSL_HAVE_BUILTIN(__is_trivially_relocatable)
GTEST_SKIP() << "No trivial ABI support.";
#endif
struct Trivial {};
struct NonTrivial {
NonTrivial(const NonTrivial&) {}
};
struct ABSL_ATTRIBUTE_TRIVIAL_ABI TrivialAbi {
TrivialAbi(const TrivialAbi&) {}
};
EXPECT_TRUE(ABSL_IS_TRIVIALLY_RELOCATABLE(Trivial));
EXPECT_FALSE(ABSL_IS_TRIVIALLY_RELOCATABLE(NonTrivial));
EXPECT_TRUE(ABSL_IS_TRIVIALLY_RELOCATABLE(TrivialAbi));
}
} // namespace

@ -42,6 +42,7 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":type_traits",
"//absl/base:core_headers",
"@com_google_googletest//:gtest_main",
],
)

@ -34,6 +34,7 @@ absl_cc_test(
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::core_headers
absl::type_traits
GTest::gmock_main
)

@ -813,6 +813,34 @@ using swap_internal::Swap;
using swap_internal::StdSwapIsUnconstrained;
} // namespace type_traits_internal
// absl::is_trivially_relocatable<T>
// Detects whether a type is "trivially relocatable" -- meaning it can be
// relocated without invoking the constructor/destructor, using a form of move
// elision.
//
// Example:
//
// if constexpr (absl::is_trivially_relocatable<T>::value) {
// memcpy(new_location, old_location, sizeof(T));
// } else {
// new(new_location) T(std::move(*old_location));
// old_location->~T();
// }
//
// Upstream documentation:
//
// https://clang.llvm.org/docs/LanguageExtensions.html#:~:text=__is_trivially_relocatable
//
#if ABSL_HAVE_BUILTIN(__is_trivially_relocatable)
template <class T>
struct is_trivially_relocatable
: std::integral_constant<bool, __is_trivially_relocatable(T)> {};
#else
template <class T>
struct is_trivially_relocatable : std::integral_constant<bool, false> {};
#endif
ABSL_NAMESPACE_END
} // namespace absl

@ -21,6 +21,7 @@
#include <vector>
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
namespace {
@ -1394,4 +1395,22 @@ TEST(TypeTraitsTest, IsNothrowSwappable) {
EXPECT_TRUE(IsNothrowSwappable<adl_namespace::SpecialNoexceptSwap>::value);
}
TEST(TrivallyRelocatable, Sanity) {
#if !defined(ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI) || \
!ABSL_HAVE_BUILTIN(__is_trivially_relocatable)
GTEST_SKIP() << "No trivial ABI support.";
#endif
struct Trivial {};
struct NonTrivial {
NonTrivial(const NonTrivial&) {} // NOLINT
};
struct ABSL_ATTRIBUTE_TRIVIAL_ABI TrivialAbi {
TrivialAbi(const TrivialAbi&) {} // NOLINT
};
EXPECT_TRUE(absl::is_trivially_relocatable<Trivial>::value);
EXPECT_FALSE(absl::is_trivially_relocatable<NonTrivial>::value);
EXPECT_TRUE(absl::is_trivially_relocatable<TrivialAbi>::value);
}
} // namespace

Loading…
Cancel
Save