> Arena management
There's nothing that stops you from using arena allocators in C++. (See pmr allocators in C++17 for handling complex non-POD types).
> The cost of RAII_
you're going to have to clean up one way or another. RAII can be zero-overhead, and usually generates less code than the C idiom of "goto Cleanup".
> Use of destructors leads toward template APIs.
Not getting that. Use of destructors leads to use of destructors. Not much else.
> If you don't use exceptions....
Why on earth would you not use exceptions? Proper error handling in C is a complete nightmare.
But even if you don't, lifetime management is a huge problem in C. Not at all trivial to clean things up when you're done. Debugging memory leaks in C code was always a nightmare. The only thing worse was debugging wild memory writes. C++ RAII: very difficult to leak things (impossible, if you're doing it right, which isn't hard), and if it ever does happen almost always related to using C apis that should have been properly wrapped with RAII in the first place.
Granted, wrapping C handles in RAII was a bit tedious in C++89; but C++17 now allows you to write a really tidy AutoClose template for doing RAII close/free of C library pointers now. Not in the standard library, but really easy to roll your own:
// call snd_pcm_close when the variable goes out of close.
using snd_pcm_T = pipedal::AutoClose<snd_pcm_t*,snd_pcm_close>;
snd_pcm_T pcm_handle = snd_pcm_open(....);
> C++ 20 undefined behavior of a read-after-free problem.That's not UB; that's a serious bug. And C's behavior would also be "UB" if you read after freeing a pointer.