13.3.1 Finally |
The discipline required to represent a resource as an object of a class with a destructor have both |
ered some. Again and again, people have inv ented ‘‘finally’’ language constructs for writing arbi |
trary code to clean up after an exception. Such techniques are generally inferior to RAII because |
they are ad hoc, but if you really want ad hoc, RAII can supply that also. First, we define a class |
that will execute an arbitrary action from its destructor. |
template<typename F> |
struct Final_action { |
Final_action(F f): clean{f} {} |
˜Final_action() { clean(); } |
F clean; |
}; |
The ‘‘finally action’’ is provided as an argument to the constructor. |
Next, we define a function that conveniently deduces the type of an action: |
template<class F> |
Final_action<F> finally(F f) |
{ |
return Final_action<F>(f); |
} |
Finally, we can test finally(): |
void test() |
// handle undiciplined resource acquisition |
// demonstrate that arbitrar y actions are possible |
{ |
int∗ p = new int{7}; | // probably should use a unique_ptr (§5.2) |
int∗ buf = (int∗)malloc(100∗sizeof(int)); | // C-style allocation |
auto act1 = finally([&]{ delete p;
free(buf); // C-style deallocation
cout<< "Goodby, Cruel world!\n";
}
);
int var = 0;
cout << "var = " << var << '\n';
// nested block:
{
var = 1;
auto act2 = finally([&]{ cout<< "finally!\n"; var=7; });
cout << "var = " << var << '\n';
} // act2 is invoked here
cout << "var = " << var << '\n';
} // act1 is invoked here