{
raii_handle *my_type = new raii_handle(new type);
....
} /// ooops
Naturally it doesn't happen just like that, rather in 500 lines of code function in code that has already been through 10 contracting agencies, including some offshored ones. {
auto p =
std::make_unique<type>;
...
} /// no oops. {
auto p =
new std::make_unique<type>;
...
} /// oops again.
The fact being the "reliability" is a good as the hundreds of developers that touched the code.Real reliabile features don't depend on their skills to actually work 100% of the time, and doing something like newing a RAII type would be a compiler error, but alas it isn't.
What matters is whether it is easier to write crap that compiles than correct code, and whether the easiest sort of crap compiles. That is where there has been progress. If you never, ever need to write "new" anymore, why would you accidentally write it?
The BS example above does not, in fact, compile, because make_unique<> is not a type. So, it illustrates the progress I cite.
One thing Ada was designed for and C++ not, was to prevent crappy developers to mess up.
Anyone that has reviewed C++ code from offshoring Asian companies is well aware of what I mean.
Bad code from dodgy, offshore outsourcing services may be in any language. Bad Ada code is no better than bad code in any other language. Bad Ada code could be worse if it often works by accident, where other code might have failed visibly and been rejected.
Ada's strictness allows it to catch many more errors at compile time than, say, C.
> Bad Ada code could be worse if it often works by accident, where other code might have failed visibly and been rejected.
This is backward. Errors will be more easily detected in Ada than in, say, C. C is full of footguns and undefined behaviour. Vanilla Ada still isn't actually a safe language, unfortunately, but as a matter of degree, it's much safer than C.
You might consider that example stupid and argue no one would ever write code like that.
To which I would answer you haven't reviewed enough offshored C++ projects.
That is the opposite of automation: everywhere you need cleanup, you have to repeat the incantation, and get it right, again, every time. The point of destructors is that they are wholly contained in the library. It takes no extra client code to run them, and they are exercised identically on every single use of the type, so are well tested. Identically the same code runs on a throw, so there is much less risk from usually poorly exercised failure cases.