mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2025-12-17 12:44:42 +03:00
Generalized E.15, closes #1848
Extended guideline to throw by value rather than by pointer
This commit is contained in:
@@ -15627,7 +15627,7 @@ Error-handling rule summary:
|
|||||||
* [E.12: Use `noexcept` when exiting a function because of a `throw` is impossible or unacceptable](#Re-noexcept)
|
* [E.12: Use `noexcept` when exiting a function because of a `throw` is impossible or unacceptable](#Re-noexcept)
|
||||||
* [E.13: Never throw while being the direct owner of an object](#Re-never-throw)
|
* [E.13: Never throw while being the direct owner of an object](#Re-never-throw)
|
||||||
* [E.14: Use purpose-designed user-defined types as exceptions (not built-in types)](#Re-exception-types)
|
* [E.14: Use purpose-designed user-defined types as exceptions (not built-in types)](#Re-exception-types)
|
||||||
* [E.15: Catch exceptions from a hierarchy by reference](#Re-exception-ref)
|
* [E.15: Throw by value, catch exceptions from a hierarchy reference](#Re-exception-ref)
|
||||||
* [E.16: Destructors, deallocation, and `swap` must never fail](#Re-never-fail)
|
* [E.16: Destructors, deallocation, and `swap` must never fail](#Re-never-fail)
|
||||||
* [E.17: Don't try to catch every exception in every function](#Re-not-always)
|
* [E.17: Don't try to catch every exception in every function](#Re-not-always)
|
||||||
* [E.18: Minimize the use of explicit `try`/`catch`](#Re-catch)
|
* [E.18: Minimize the use of explicit `try`/`catch`](#Re-catch)
|
||||||
@@ -16076,41 +16076,48 @@ The standard-library classes derived from `exception` should be used only as bas
|
|||||||
|
|
||||||
Catch `throw` and `catch` of a built-in type. Maybe warn about `throw` and `catch` using a standard-library `exception` type. Obviously, exceptions derived from the `std::exception` hierarchy are fine.
|
Catch `throw` and `catch` of a built-in type. Maybe warn about `throw` and `catch` using a standard-library `exception` type. Obviously, exceptions derived from the `std::exception` hierarchy are fine.
|
||||||
|
|
||||||
### <a name="Re-exception-ref"></a>E.15: Catch exceptions from a hierarchy by reference
|
### <a name="Re-exception-ref"></a>E.15: Throw by value, catch exceptions from a hierarchy reference
|
||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
To prevent slicing.
|
|
||||||
|
|
||||||
##### Example
|
##### Example; bad
|
||||||
|
|
||||||
void f()
|
void f()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// ...
|
// ...
|
||||||
|
throw new widget{}; // don't: throw by value not by raw pointer
|
||||||
|
// ...
|
||||||
}
|
}
|
||||||
catch (exception e) { // don't: might slice
|
catch (base_class e) { // don't: might slice
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Instead, use a reference:
|
Instead, use a reference:
|
||||||
|
|
||||||
catch (exception& e) { /* ... */ }
|
catch (base_class& e) { /* ... */ }
|
||||||
|
|
||||||
or - typically better still - a `const` reference:
|
or - typically better still - a `const` reference:
|
||||||
|
|
||||||
catch (const exception& e) { /* ... */ }
|
catch (const base_class& e) { /* ... */ }
|
||||||
|
|
||||||
Most handlers do not modify their exception and in general we [recommend use of `const`](#Res-const).
|
Most handlers do not modify their exception and in general we [recommend use of `const`](#Res-const).
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
|
Catch by value can be appropriate for a small value type such as an `enum` value.
|
||||||
|
|
||||||
|
##### Note
|
||||||
|
|
||||||
To rethrow a caught exception use `throw;` not `throw e;`. Using `throw e;` would throw a new copy of `e` (sliced to the static type `std::exception`) instead of rethrowing the original exception of type `std::runtime_error`. (But keep [Don't try to catch every exception in every function](#Re-not-always) and [Minimize the use of explicit `try`/`catch`](#Re-catch) in mind.)
|
To rethrow a caught exception use `throw;` not `throw e;`. Using `throw e;` would throw a new copy of `e` (sliced to the static type `std::exception`) instead of rethrowing the original exception of type `std::runtime_error`. (But keep [Don't try to catch every exception in every function](#Re-not-always) and [Minimize the use of explicit `try`/`catch`](#Re-catch) in mind.)
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
Flag by-value exceptions if their types are part of a hierarchy (could require whole-program analysis to be perfect).
|
- Flag catching by value of a type that has a virtual function.
|
||||||
|
- Flag throwing raw pointers.
|
||||||
|
|
||||||
|
|
||||||
### <a name="Re-never-fail"></a>E.16: Destructors, deallocation, and `swap` must never fail
|
### <a name="Re-never-fail"></a>E.16: Destructors, deallocation, and `swap` must never fail
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user