<batteries/status.hpp>: Efficient, Ergonomic Error Handling
<batteries/status.hpp>: Efficient, Ergonomic Error Handling🔗
Summary🔗
Why not exceptions?🔗
Batteries C++ discourages the use of exceptions as an error handling mechanism. Exceptions tend to hurt the readability and maintainability of code because they introduce non-local control flow (throw statements can jump to catch statements arbitrarily far away with no obvious connection between the two points), break the separation of interface and implementation (because implementations can silently introduce new failure modes because of a deep change, even several layers down), and add to the complexity of syntax because when you program with exceptions now there are multiple ways to return a value from a function, each with its own caveats and idiosyncrasies. The purported benefit of exceptions, that they clean up the code by hiding error handling code, does more harm than good because failure modes are an essential element to understanding any code.
What instead of exceptions? (batt::Status)🔗
In place of exceptions, Batteries provides batt::Status
and many related constructs.
DISCLAIMER/ACKNOWLEDGMENT: batt::Status is modelled very closely after absl::Status from Google's Abseil library.
A batt::Status
is like an exception in that it represents a specific error condition, but it can also represent no error at all. When a function that returns a value, say an int
, can also fail, it is best to write it as:
In this example, we imagine a function that takes a string and parses it as an integer value. Because this operation may fail (if for example it is handed an invalid string like "hello, world"), we declare the return type as batt::StatusOr<int>
.
Functions returning no value that can fail should just return batt::Status
.
To make the use of Status
easier in practice, Batteries provides several macros to automatically unwrap a Status
or propagate it up a call stack. Example:
Standard Status Codes🔗
Batteries provides the same standard status codes as Abseil Status, plus a few extras:
Handling System Errors🔗
In addition, batt::Status
can accept standard errno
values from system calls:
In fact, because this pattern is so common when invoking system APIs, the above example can also be written as:
batt::Status🔗
Summary🔗
Constructors | Operators | Methods | |
---|---|---|---|
Status() | operator= | ok | group |
Status(enum_value) | operator<< | code | IgnoreError |
Status(const Status&) | operator== | message | Update |
Static Methods | Types | Constants |
---|---|---|
code_group_for_type | value_type | kGroupSizeBits |
message_from_code | CodeEntry | kGroupSize |
register_codes | CodeGroup | kMaxGroups |
unknown_enum_value_message |