| 671 | |
| 672 | template <typename T, typename... Args> |
| 673 | Unique<T> AllocateUnique(Allocator<> allocator, Args&&... args) { |
| 674 | using U = std::remove_cv_t<T>; |
| 675 | static_assert(!std::is_reference_v<U>, "T must not be a reference"); |
| 676 | static_assert(!std::is_array_v<U>, "T must not be an array"); |
| 677 | |
| 678 | U* object; |
| 679 | google::protobuf::Arena* absl_nullable arena = allocator.arena(); |
| 680 | bool unowned; |
| 681 | if constexpr (google::protobuf::Arena::is_arena_constructable<U>::value) { |
| 682 | object = google::protobuf::Arena::Create<U>(arena, std::forward<Args>(args)...); |
| 683 | // For arena-compatible proto types, let the Arena::Create handle |
| 684 | // registering the destructor call. |
| 685 | // Otherwise, Unique<T> retains a pointer to the owning arena so it may |
| 686 | // conditionally register T::~T depending on usage. |
| 687 | unowned = false; |
| 688 | } else { |
| 689 | void* p = allocator.allocate_bytes(sizeof(U), alignof(U)); |
| 690 | CEL_INTERNAL_TRY { |
| 691 | if constexpr (ArenaTraits<>::constructible<U>()) { |
| 692 | object = ::new (p) U(arena, std::forward<Args>(args)...); |
| 693 | } else { |
| 694 | object = ::new (p) U(std::forward<Args>(args)...); |
| 695 | } |
| 696 | } |
| 697 | CEL_INTERNAL_CATCH_ANY { |
| 698 | allocator.deallocate_bytes(p, sizeof(U), alignof(U)); |
| 699 | CEL_INTERNAL_RETHROW; |
| 700 | } |
| 701 | unowned = |
| 702 | arena != nullptr && !ArenaTraits<>::trivially_destructible(*object); |
| 703 | } |
| 704 | return Unique<T>(object, arena, unowned); |
| 705 | } |
| 706 |
nothing calls this directly
no test coverage detected