Error handling
E.14
Use purpose-designed user-defined types as exceptions (not built-in types)
Reason
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
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 MyException{"something bad"}; // good
Exceptions do not need to be derived from std::exception:
class MyCustomError final {}; // not derived from std::exception
// ...
throw MyCustomError{}; // good - handlers must catch this type (or ...)
Library types derived from std::exception can be used as generic exceptions if no useful information can be added at the point of detection:
throw std::runtime_error("something bad"); // good
// ...
throw std::invalid_argument("i is not even"); // good
enum classes are also allowed:
enum class alert {RED, YELLOW, GREEN};
throw alert::RED; // good
Enforcement
Catch throw of built-in types and std::exception.