Combine rules C.36 and C.37
Rule C.36 states "A destructor must not fail" and rule C.37 states "Make destructors noexcept". There are a couple of reasons to combine these 2 rules:
- Both rules are about the same thing: a destructor should not fail but if it fails for some reason make sure it aborts the program.
- One of the notes in rule C.36 is "Declare a destructor noexcept", which is the synopsis of rule C.37.
- The justification of rule C.37 starts with "A destructor must not fail", which is the synopsis of rule C.36.
- Both rules have the same enforcement.
If somebody can confirm my reasoning, I will create a pull request that combines both rules. Let me know.
The guidelines you're referring to from the C++ Core Guidelines emphasize the importance of ensuring that destructors do not throw exceptions. The reason behind this is to maintain program stability and to prevent resource leaks, which can occur if an exception is thrown during the stack unwinding process of another exception.
Here are the two rules and their explanations:
Rule C.36: A destructor must not fail
The key idea behind this rule is that destructors are responsible for releasing resources, and if a destructor fails (throws an exception), it can lead to undefined behavior and resource leaks. During stack unwinding (when an exception is thrown and caught), destructors are called for objects that go out of scope. If another exception is thrown during this process, the program may terminate.
Rule C.37: Make destructors 'noexcept'
This rule complements C.36 by ensuring that destructors are explicitly marked as 'noexcept'. By marking destructors 'noexcept', you guarantee that they will not throw exceptions, reinforcing the idea that destructors must not fail. It also allows the compiler to optimize certain operations and ensures the program's correctness during stack unwinding.
Combining the Rules Both rules effectively convey the same principle: destructors should not throw exceptions. Marking a destructor as 'noexcept' enforces this at the language level, while the rule that destructors must not fail emphasizes the best practice from a design perspective.
code class Resource { public: Resource() { // Allocate some resource }
~Resource() noexcept {
try {
// Release the resource
} catch (...) {
// Log the error if needed
// Do not throw from a destructor
}
}
};
Why the Combination Makes Sense Consistency: By combining these rules, the guidelines provide a consistent approach to handle destructors, ensuring that they adhere to best practices and are easy to understand. Safety: Declaring destructors as noexcept ensures that the compiler and runtime can safely handle stack unwinding without the risk of unexpected exceptions. Clarity: Having a single combined rule makes it clear that destructors should be written in a way that they do not throw exceptions, and marking them 'noexcept' is a way to enforce this.
Editors call: Thanks! We agree the two have the same Enforcement because we want the rules to stand on their own, but we think of C.37 as "an" implementation of C.36.