avasilev wrote:
Hi all
Its one of my little pragramming challenges to implement a try/finally
construct in C++. I have done several implementations but they all have
limitations.
An unwind protect mechanism is architectural. If it's not in the
substrate, it may be impossible to implement 100%. There are semantic
pieces in C++ that could do the job, but the syntactic abstraction
isn't there.
I'm curious to see other ideas
Firstly, separate the finally mechanism from try and catch. Conflating
them together is an unnecessary Java thing which you don't have to
adopt. In some other languages, the mechanism that means "execute this
regardless of how this terminates" is a separate construct. Common Lisp
calls it unwind-protect, a term that is sometimes used outside of Lisp
to refer to any such a mechanism..
If you separate it out, you have a simpler job, because your syntax
does not have to incorporate catch blocks for exceptions. It has only
two pieces: the block that is protected, and the code that is run
unconditionally.
The problem is that you need the unconditional code in two places:
immediately following the protected code (normal return case) and in a
catch (...) handler.
To do this, you can make the entire code into a giant macro argument,
by doing which you end up with something that combines ugly appearance
with debugger hostility:
#include <iostream>
#define ugly_unwind_protect(block, cleanup) \
try { block } catch (...) { cleanup throw; } cleanup
int main()
{
int x = 3;
try {
ugly_unwind_protect (
{
throw 42;
},
{
// demonstrate access to locals
std::cout << "x = " << x << std::endl;
}
)
} catch (int ex) {
// the 42 is caught here
std::cout << "ex = " << ex << std::endl;
}
return 0;
}
Oh yeah, because statements are passed as a single macro argument,
commas in them can cause problems. Try changing it to "throw 0, 42" and
see, hahaha. That's only a problem for commas that are not enclosed in
parentheses.
As you can see, you can get all the functionality of try/catch/finally
with try/catch and a separate unwind-protect.
Note how the unwind code is duplicated textually in two places. Yuck!