> in this case, the RAII wrapper should provide a member function which can execute the underlying close call early and expose the failure, for users who may be interested in guaranteed reliability.
Indeed; this is a useful technique. However, it means that you now have a close() method which you have to call on every exit path, because if you miss a path, that's a path which could have an exception thrown from a destructor. And that basically means you're not doing RAII anymore.
So yes, RAII is intrinsically incompatible with this kind of reliability.
> However, it means that you now have a close() method which you have to call on every exit path, because if you miss a path, that's a path which could have an exception thrown from a destructor.
Not true at all. `close` and the destructor should be idempotent. In the main path, `close` will get called and failure will propogate upward. In any other failure path, the destructor will attempt to perform the underlying close and allow the stack to unwind without any further interruption.
Of course, anyone can come up with pathological cases where this is not acceptable behavior from a high-reliability sub-component. And in such a situation, RAII may not be the best answer (nor would lexical scoping i.e. constructor/destructor, for that matter!) But in my experience, this approach is just fine for most application-level code.
Indeed; this is a useful technique. However, it means that you now have a close() method which you have to call on every exit path, because if you miss a path, that's a path which could have an exception thrown from a destructor. And that basically means you're not doing RAII anymore.
So yes, RAII is intrinsically incompatible with this kind of reliability.