Use `if constexpr` instead of `absl::utility_internal::IfConstexprElseIfConstexprElse`

PiperOrigin-RevId: 728737911
pull/20383/head
Derek Mauro 1 month ago committed by Copybara-Service
parent 28de0ebcdd
commit 0ea5ccd61c
  1. 61
      src/google/protobuf/arena.h

@ -32,7 +32,6 @@ using type_info = ::type_info;
#include "absl/base/optimization.h"
#include "absl/base/prefetch.h"
#include "absl/log/absl_check.h"
#include "absl/utility/internal/if_constexpr.h"
#include "google/protobuf/arena_align.h"
#include "google/protobuf/arena_allocation_policy.h"
#include "google/protobuf/port.h"
@ -195,41 +194,31 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
// otherwise, returns a heap-allocated object.
template <typename T, typename... Args>
PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) {
return absl::utility_internal::IfConstexprElse<
is_arena_constructable<T>::value>(
// Arena-constructable
[arena](auto&&... args) {
using Type = std::remove_const_t<T>;
#ifdef __cpp_if_constexpr
// DefaultConstruct/CopyConstruct are optimized for messages, which
// are both arena constructible and destructor skippable and they
// assume much. Don't use these functions unless the invariants
// hold.
if constexpr (is_destructor_skippable<T>::value) {
constexpr auto construct_type = GetConstructType<T, Args&&...>();
// We delegate to DefaultConstruct/CopyConstruct where appropriate
// because protobuf generated classes have external templates for
// these functions for code size reasons. When `if constexpr` is not
// available always use the fallback.
if constexpr (construct_type == ConstructType::kDefault) {
return static_cast<Type*>(DefaultConstruct<Type>(arena));
} else if constexpr (construct_type == ConstructType::kCopy) {
return static_cast<Type*>(CopyConstruct<Type>(arena, &args...));
}
}
#endif
return CreateArenaCompatible<Type>(arena,
std::forward<Args>(args)...);
},
// Non arena-constructable
[arena](auto&&... args) {
if (ABSL_PREDICT_FALSE(arena == nullptr)) {
return new T(std::forward<Args>(args)...);
}
return new (arena->AllocateInternal<T>())
T(std::forward<Args>(args)...);
},
std::forward<Args>(args)...);
if constexpr (is_arena_constructable<T>::value) {
using Type = std::remove_const_t<T>;
// DefaultConstruct/CopyConstruct are optimized for messages, which
// are both arena constructible and destructor skippable and they
// assume much. Don't use these functions unless the invariants
// hold.
if constexpr (is_destructor_skippable<T>::value) {
constexpr auto construct_type = GetConstructType<T, Args&&...>();
// We delegate to DefaultConstruct/CopyConstruct where appropriate
// because protobuf generated classes have external templates for
// these functions for code size reasons. When `if constexpr` is not
// available always use the fallback.
if constexpr (construct_type == ConstructType::kDefault) {
return static_cast<Type*>(DefaultConstruct<Type>(arena));
} else if constexpr (construct_type == ConstructType::kCopy) {
return static_cast<Type*>(CopyConstruct<Type>(arena, &args...));
}
}
return CreateArenaCompatible<Type>(arena, std::forward<Args>(args)...);
} else {
if (ABSL_PREDICT_FALSE(arena == nullptr)) {
return new T(std::forward<Args>(args)...);
}
return new (arena->AllocateInternal<T>()) T(std::forward<Args>(args)...);
}
}
// API to delete any objects not on an arena. This can be used to safely

Loading…
Cancel
Save