|
9 | 9 |
|
10 | 10 | #include <variant> |
11 | 11 |
|
12 | | -/* |
13 | | - * 'BResult' is a generic class useful for wrapping a return object |
14 | | - * (in case of success) or propagating the error cause. |
15 | | -*/ |
| 12 | +namespace util { |
| 13 | + |
| 14 | +struct Error { bilingual_str message; }; |
| 15 | + |
| 16 | +//! The util::Result class provides a standard way for functions to return error |
| 17 | +//! messages in addition to optional result values. |
| 18 | +//! |
| 19 | +//! It is intended for high-level functions that need to report error strings to |
| 20 | +//! end users. Lower-level functions that don't need this error-reporting and |
| 21 | +//! only need error-handling should avoid util::Result and instead use standard |
| 22 | +//! classes like std::optional, std::variant, and std::tuple, or custom structs |
| 23 | +//! and enum types to return function results. |
| 24 | +//! |
| 25 | +//! Usage examples can be found in \example ../test/result_tests.cpp, but in |
| 26 | +//! general code returning `util::Result<T>` values is very similar to code |
| 27 | +//! returning `std::optional<T>` values. Existing functions returning |
| 28 | +//! `std::optional<T>` can be updated to return `util::Result<T>` and return |
| 29 | +//! error strings usually just replacing `return std::nullopt;` with `return |
| 30 | +//! util::Error{error_string};`. |
16 | 31 | template<class T> |
17 | | -class BResult { |
| 32 | +class Result { |
18 | 33 | private: |
19 | 34 | std::variant<bilingual_str, T> m_variant; |
20 | 35 |
|
| 36 | + template <typename FT> |
| 37 | + friend class Result; |
| 38 | + template <typename FT> |
| 39 | + friend bilingual_str ErrorString(const Result<FT>& result); |
| 40 | + |
21 | 41 | public: |
22 | | - BResult() : m_variant{Untranslated("")} {} |
23 | | - BResult(T obj) : m_variant{std::move(obj)} {} |
24 | | - BResult(bilingual_str error) : m_variant{std::move(error)} {} |
25 | | - |
26 | | - /* Whether the function succeeded or not */ |
27 | | - bool HasRes() const { return std::holds_alternative<T>(m_variant); } |
28 | | - |
29 | | - /* In case of success, the result object */ |
30 | | - const T& GetObj() const { |
31 | | - assert(HasRes()); |
32 | | - return std::get<T>(m_variant); |
33 | | - } |
34 | | - T ReleaseObj() |
35 | | - { |
36 | | - assert(HasRes()); |
37 | | - return std::move(std::get<T>(m_variant)); |
38 | | - } |
39 | | - |
40 | | - /* In case of failure, the error cause */ |
41 | | - const bilingual_str& GetError() const { |
42 | | - assert(!HasRes()); |
43 | | - return std::get<bilingual_str>(m_variant); |
44 | | - } |
45 | | - |
46 | | - explicit operator bool() const { return HasRes(); } |
| 42 | + Result(T obj) : m_variant{std::move(obj)} {} |
| 43 | + Result(Error error) : m_variant{std::move(error.message)} {} |
| 44 | + template <typename OT> |
| 45 | + Result(Error error, Result<OT>&& other) : m_variant{std::move(std::get<0>(other.m_variant))} {} |
| 46 | + |
| 47 | + //! std::optional methods, so functions returning optional<T> can change to |
| 48 | + //! return Result<T> with minimal changes to existing code, and vice versa. |
| 49 | + bool has_value() const { return m_variant.index() == 1; } |
| 50 | + const T& value() const { assert(*this); return std::get<1>(m_variant); } |
| 51 | + T& value() { assert(*this); return std::get<1>(m_variant); } |
| 52 | + template <typename U> |
| 53 | + T value_or(const U& default_value) const { return has_value() ? value() : default_value; } |
| 54 | + operator bool() const { return has_value(); } |
| 55 | + const T* operator->() const { return &value(); } |
| 56 | + const T& operator*() const { return value(); } |
| 57 | + T* operator->() { return &value(); } |
| 58 | + T& operator*() { return value(); } |
47 | 59 | }; |
48 | 60 |
|
| 61 | +template <typename T> |
| 62 | +bilingual_str ErrorString(const Result<T>& result) |
| 63 | +{ |
| 64 | + return result ? bilingual_str{} : std::get<0>(result.m_variant); |
| 65 | +} |
| 66 | +} // namespace util |
| 67 | + |
49 | 68 | #endif // BITCOIN_UTIL_RESULT_H |
0 commit comments