![]() |
Zen C++ Libraries
Zero-dependency re-usable components for C++
|
Encapsulation for computations that may fail. More...
#include <condition_variable>#include <type_traits>#include <utility>#include "zen/config.hpp"#include "zen/formatting.hpp"Go to the source code of this file.
Classes | |
| struct | dummy |
| class | either< L, R > |
| A type for computations that may fail. More... | |
Macros | |
| #define | ZEN_TRY(value) |
| Return a left-valued immediately so only a right-valued either type remains. | |
| #define | ZEN_TRY_DISCARD(expr) |
| The same as ZEN_TRY but the expression is immediately dropped. | |
Functions | |
| left_t< void > | left () |
| template<typename L> | |
| left_t< L & > | left (L &value) |
| template<typename L> | |
| left_t< L > | left (L &&value) |
| right_t< void > | right () |
| template<typename R> | |
| right_t< R & > | right (R &value) |
| template<typename R> | |
| right_t< R > | right (R &&value) |
Encapsulation for computations that may fail.
A common idiom is to use the type defined in this header on functions that can fail, as an alternatve to exception handling. Some hold that this is a good practice for several reasons:
Often, you find yourself interfacing with external systems, such as a network service or the file system. Doing operations on these objects can result in failures, e.g. an ENOENT returned from a call to stat().
In C, it is very common to store the actual result in one of the function's parameters and return an error code, like so:
In C++ another common idiom is returning a nullptr whenever a heap-allocated object could not be created. These approaches have obvious drawbacks. In the case of returning an error code instead of the result, we have to make sure our variable can be kept as a reference, leading to more code.
The generic solution to this problem is to introduce a new type, called either, that can hold both a result and an error code, without wasting precious memory. This is exactly what zen::either<L, R> was made for.
We can further improve upon our code snippet by declaring an enum that lists all possible errors that might occur. The errors might even be full classes using virtual inheritance; something which we'll see later on.
Finally, we encapsulate our error type in a custom Result-type that will be used thoughout our application:
That's it! You've learned how to write simple C++ code the Zen way!
| #define ZEN_TRY | ( | value | ) |
Return a left-valued immediately so only a right-valued either type remains.
The remaining value can be safely unwrapped.
| #define ZEN_TRY_DISCARD | ( | expr | ) |
The same as ZEN_TRY but the expression is immediately dropped.
|
inline |
Construct a left-valued either type that has no contents.
Usually, this means that the computation failed but no particular error needed to be specified.
In Rust, one would return Err(()).
| left_t< L > left | ( | L && | value | ) |
Construct a left-valued either type. The provided value will be moved into the either type.
Usually, this means that a computation has failed and an error should be returned.
In Rust, one would write Err(value).
| left_t< L & > left | ( | L & | value | ) |
Construct a left-valued either type. The provided value will be copied into the either type.
Usually, this means that a computation has failed and an error should be returned.
In Rust, one would write Err(value).
|
inline |
Construct a right-valued either type that has no contents.
Usually, this means that the computation was successful but no particular value was generated during its run.
In Rust, one would return Ok(()).
| right_t< R > right | ( | R && | value | ) |
Construct a right-valued either type. The provided value will be copied into the either type.
Usually, this means that the computation was successful and generated exactly one value.
In Rust, one would return Ok(value).
| right_t< R & > right | ( | R & | value | ) |
Construct a right-valued either type. The provided value will be moved into the either type.
Usually, this means that the computation was successful and generated exactly one value.
In Rust, one would return Ok(value).