I came across a class instance function that required to temporarily change the class instance variable and then restore it when the function exited. The function had return statements all over the place, and an instruction returned before each return. It seemed messy to me, not to mention that it's scary when an exception occurs.
As an improvement, I came up with this generalization using the definition of an inner class. Here is an example of a program driver (restorer class).
class Unwind { private: bool b_active_; ///< the thing I want to be restored template<typename T> class restorer { T* ref_; T save_; public: restorer(T* perm) : ref_(perm), save_(*ref_) {}; ~restorer() { *ref_ = save_; } }; public: Unwind() : b_active_(false) {}; void a() { out("a in"); b(); out("a end"); } void b() { out("b in"); { restorer<bool> trust_in_the_stack(&b_active_); // "restorer" created on the stack b_active_ = true; // change b_active_ only while "within" b() c(); out("b inner end"); } out("b end"); } void c() { out("c in"); d(); out("c end"); } void d() { out("d in"); cout << "deepest" << endl; out("d end"); } void out(const std::string& msg) { std::cout << msg << ": " << b_active_ << std::endl; } }; int main() { Unwind u; ua(); return 0; }
The output using g ++ 4.2.3 (-Wall) was:
a in: 0
b in: 0
c in: 1
d in: 1
deepest
d end: 1
c end: 1
b inner end: 1
b end: 0
a end: 0
This is what I expect at the end of "b".
I felt that defining a class restorer inside an Unwind class helps to discard misuse.
My question is: is there a general and safe way to do this? I am worried about life issues.
Edit: Assume that there are no threads on the stack, but "downstream" methods that change behavior based on this flag b_active_.
source share