From 4cafd1f2bcc733e6aa121fc0810e06f622348a89 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 26 Aug 2024 16:32:04 -0700 Subject: [PATCH] Scopeguard advice. --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index 3b6d94a..d7fb487 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ error in the function's signature. Documenting *which* exceptions can be thrown or errors reported is not crucial, but documenting the fact *that* an error can occur is. + Unless otherwise specified in the function's documentation, a reported error means all objects the function would otherwise modify are invalid for all uses, except as the target of destruction or @@ -324,6 +325,33 @@ target_link_libraries(my-executable PRIVATE adobe-contract-checks) implementations should call the `check_invariant()`(s) of their parent classes. + If your mutating function has multiple returns, it might be useful + to wrap your `check_invariant()` call in + [`boost::scope_success`](https://www.boost.org/doc/libs/master/libs/scope/doc/html/scope/scope_guards.html#scope.scope_guards.conditional) + (which also [may be + available](https://en.cppreference.com/w/cpp/experimental/scope_success) + in your implementation's `std::experimental` namespace), at the beginning + of the function. + + ```c++ + void mutate_me() { + std::experimental::scope_success _([&]{ check_invariant(); }); + ... + } + ``` + + **Caveats:** + + 1. You still need to call `check_invariant()` anywhere the object + under mutation may exposed outside the class other than by + returning, e.g. if it is passed to a callback function. + + 2. If your function reports errors to the caller other than by + exception (e.g. in the return value), this technique will force + your invariant to be checked even in the event of an error, which + is [inappropriate](#reported-errors-and-class-invariants), and + may force you to weaken the invariant. + - If your program needs to take emergency shutdown measures before termination, put those in a [terminate handler](https://en.cppreference.com/w/cpp/error/terminate_handler)