struct OnExit{ int &i; OnExit(int &i_) : i(i_) {}; ~OnExit() { if (!std::uncaught_exception()) { some-code } };} onexit(i);struct OnError{ int &i; OnError(int &i_) : i(i_) {}; ~OnError() { if (std::uncaught_exception()) { some-code } };} onerror(i);struct OnExitOrError{ int &i; OnExitOrError(int &i_) : i(i_) {}; ~OnExitOrError() { some-code };} onexitorerror(i);
This is a local class by the way. The "i" parameter in the constructor is a local variable that you wanna test in the "some-code" part -- there is no other way to access the caller's context. So you'd need to repeat that pattern for a number of variables that you want to use. The storage type (in this case int) must also be specified. It seems that templates aren't legal in local classes, which is a shame.
Anyways, the really neat thing is that as long as the internal references to the local variables have the same names as said local variables, you can just take some code that used to be in the original function, put it inside the local class unchanged and it just works.
The macros are supposed to replicate that up to a certain number of parameters, let you specify the local vars and their types, and also give each instance a different name to prevent conflicts in case you use several of these.
Feel free to punch a whole through it though :)
I'm not so sure about the names (OnExit is where you're supposed to put your assert()'s), and maybe there are some cases I forgot where this will not work.
EDIT
It works now, I just need to find a place to post it up. Example usage:
double my_sqrt(double x) { double res; // pre-conditions: assert( x > 0 ); // post-conditions: OnExit2(double,x, double,res, { assert( res * res == x ); }); // main function body res = sqrt(x); // uncomment the following line to crash this thing // (post-condition won't verify) //res++; return res;}void main() { cout<<"Sqrt(30)="<<my_sqrt(30);}
[Edited by - Jotaf on December 22, 2008 7:54:48 PM]