I think arenas are more of an alternative to shared_ptr than to unique_ptr.
A std::string is an example we can use, it acts fairly similar to unique_ptr. Sometimes you just need to heap allocate something, work with it and/or store it as a member, maybe pass it to a function or whatever, and then have it cleaned up at the end of the scope or when the object that it's a member of is destroyed. I don't think an arena can replace this use case.
If we need something with multiple handles, that doesn't have a trivial and predictable lifetime (such as objects / variables in a programming language interpreter, or entities in a video game), you can reach for shared_ptr or an arena. In the specific example I gave I would certainly prefer the arena, and would implement a garbage collector to deallocate stuff when it became unreachable.
The arena pattern is fairly common in Rust, because in Rust even a reference counted smart pointer doesn't let you bypass the "shared ^ mutable" enforcement from the borrow checker! Having everything owned by the arena greatly simplifies issues with the borrowck, and you can just allow callers to take temporary references and drop them when they are finished with them. There is a crate called "SlotMap" that provides a data structure to assist with the pattern (there is a C++ SlotMap library as well somewhere).
Anyways I have rambled a bit, but I think unique_ptr solves a different problem than what you describe, which instead is more of an alternative to reference counted pointers (shared_ptr).
Most typically when using arenas, you don't want to pay the cost of de-allocation at all while the arena is still alive. So, you actually have to "fight" unique_ptr, since you don't want it to call any kind of delete() or destructor, and you essentially get nothing in return.
If you use a bare pointer instead, not only do you get the same guarantees, but now if you need to modify the code to actually share that object, there's no need to modify any references from unique_ptr to shared_ptr.
Yeah! That's what I meant when I said arenas solve a different problem! I don't think I mentioned using unique_ptr with the arena and I didn't mean to suggest that if I did. My point was that arenas are not a replacement for unique_ptr at all, and instead solve a different problem where allocations don't have a simple and deterministic lifetime.
With an arena ideally you can just pass out actual references (T&) to callers instead of pointers!
I believe that there are certain situations where one may choose between scope-based memory management and arena-based. Even for the example of the rendering code of a frame, instead of allocating inside an arena, you could choose to allocate an object graph owned by some frame-level object, that is de-allocated once the frame is rendered.
A std::string is an example we can use, it acts fairly similar to unique_ptr. Sometimes you just need to heap allocate something, work with it and/or store it as a member, maybe pass it to a function or whatever, and then have it cleaned up at the end of the scope or when the object that it's a member of is destroyed. I don't think an arena can replace this use case.
If we need something with multiple handles, that doesn't have a trivial and predictable lifetime (such as objects / variables in a programming language interpreter, or entities in a video game), you can reach for shared_ptr or an arena. In the specific example I gave I would certainly prefer the arena, and would implement a garbage collector to deallocate stuff when it became unreachable.
The arena pattern is fairly common in Rust, because in Rust even a reference counted smart pointer doesn't let you bypass the "shared ^ mutable" enforcement from the borrow checker! Having everything owned by the arena greatly simplifies issues with the borrowck, and you can just allow callers to take temporary references and drop them when they are finished with them. There is a crate called "SlotMap" that provides a data structure to assist with the pattern (there is a C++ SlotMap library as well somewhere).
Anyways I have rambled a bit, but I think unique_ptr solves a different problem than what you describe, which instead is more of an alternative to reference counted pointers (shared_ptr).