From 43f2e34148fc6ded8fd0f54899a4c1864726a2d2 Mon Sep 17 00:00:00 2001 From: bgloyer <36457894+bgloyer@users.noreply.github.com> Date: Thu, 27 Jan 2022 13:10:34 -0800 Subject: [PATCH] E.14 exception type examples for #1852 (#1857) * E.14 * clean-up * add final * Added words to dictionary * cleanup * fix typo * Update CppCoreGuidelines.md --- CppCoreGuidelines.md | 88 ++++++++++++++----------------------- scripts/hunspell/isocpp.dic | 2 + 2 files changed, 34 insertions(+), 56 deletions(-) diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index f1fed7c..dbff7fa 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -15992,80 +15992,56 @@ Sometimes, [`finally()`](#Re-finally) can make such unsystematic cleanup a bit m ##### Reason -A user-defined type is unlikely to clash with other people's exceptions. +A user-defined type can better transmit information about an error to a handler. Information +can be encoded into the type itself and the type is unlikely to clash with other people's exceptions. ##### Example - void my_code() + throw 7; // bad + + throw "something bad"; // bad + + throw std::exception{}; // bad - no info + +Deriving from `std::exception` gives the flexibility to catch the specific exception or handle generally through `std::exception`: + + class MyException : public std::runtime_error { + public: + MyException(const string& msg) : std::runtime_error{msg} {} // ... - throw Moonphase_error{}; - // ... - } + }; - void your_code() - { - try { - // ... - my_code(); - // ... - } - catch(const Bufferpool_exhausted&) { - // ... - } - } + // ... -##### Example, don't + throw MyException{"something bad"}; // good - void my_code() // Don't - { - // ... - throw 7; // 7 means "moon in the 4th quarter" - // ... - } +Exceptions do not need to be derived from `std::exception`: - void your_code() // Don't - { - try { - // ... - my_code(); - // ... - } - catch(int i) { // i == 7 means "input buffer too small" - // ... - } - } + class MyCustomError final {}; // not derived from std::exception -##### Note + // ... -The standard-library classes derived from `exception` should be used only as base classes or for exceptions that require only "generic" handling. Like built-in types, their use could clash with other people's use of them. + throw MyCustomError{}; // good - handlers must catch this type (or ...) -##### Example, don't +Library types derived from `std::exception` can be used as generic exceptions if +no useful information can be added at the point of detection: - void my_code() // Don't - { - // ... - throw runtime_error{"moon in the 4th quarter"}; - // ... - } + throw std::runtime_error("someting bad"); // good - void your_code() // Don't - { - try { - // ... - my_code(); - // ... - } - catch(const runtime_error&) { // runtime_error means "input buffer too small" - // ... - } - } + // ... + + throw std::invalid_argument("i is not even"); // good -**See also**: [Discussion](#Sd-???) +`enum` classes are also allowed: + + enum class alert {RED, YELLOW, GREEN}; + + throw alert::RED; // good ##### Enforcement -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` of built-in types and `std::exception`. ### E.15: Throw by value, catch exceptions from a hierarchy by reference diff --git a/scripts/hunspell/isocpp.dic b/scripts/hunspell/isocpp.dic index 39f00ce..ef45e4e 100644 --- a/scripts/hunspell/isocpp.dic +++ b/scripts/hunspell/isocpp.dic @@ -343,6 +343,8 @@ Murray93 mutex mutexes mx +MyCustomError +MyException myMap MyMap myset