Since there is no finally
in C++ you have to use the RAII design pattern instead, if you want your code to be exception safe. One way to do this is by using the destructor of a local class like this:
void foo() {
struct Finally {
~Finally() { /* cleanup code */ }
} finalizer();
// ...code that might throw an exception...
}
This is a big advantage over the straight forward solution, because you don't have to write the cleanup code 2 times:
try {
// ...code that might throw an exception...
// cleanup code (no exception)
} catch (...) {
// cleanup code (exception)
throw;
}
A big disadvantage of the local class solution is that you can't directly access local variables in your cleanup code. So it will bloat your code a lot if you need access to them regardless:
void foo() {
Task* task;
while (task = nextTask()) {
task->status = running;
struct Finally {
Task* task;
Finally(Task* task) : task(task) {}
~Finally() { task->status = idle; }
} finalizer(task);
// ...code that might throw an exception...
}
}
So my question is: Is there a solution which combines both advantages? So that you a) don't have to write duplicate code and b) can access local variables in the cleanup code, like task
in the last example, but without such code bloat.
Instead of defining struct Finally
, you could extract your cleanup code in a function of the class Task
and use Loki's ScopeGuard.
ScopeGuard guard = MakeGuard(&Task::cleanup, task);
See also this DrDobb's article and this other article for more about ScopeGuards.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With