From 5c345e19fdaab13f85a330a6e16ca75b681f2382 Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 14 Dec 2022 23:54:04 -0600 Subject: [PATCH] refactor: convert maybe_error into generic `Result` template class This is a simple implementation of the Result type in C++. The Result type is a type that can either be an Ok value, which represents a successful operation and contains a value, or an Err value, which represents a failed operation and contains an error value. The Result class is a template class that takes two types: T, which is the type of the value that an Ok result will contain, and E, which is the type of the value that an Err result will contain. The Ok and Err structs are also templates, and are used to construct Ok and Err values. The Ok struct has an optional single member val_ of type T, and the Err struct has a single member val_ of type E. The Result class has a constructor that takes either an Ok value or an Err value, and stores the value internally. It also has several member functions that can be used to access the value of the Result and check whether it is an Ok or Err value. The is_ok() and is_err() member functions can be used to check whether the Result is an Ok or Err value, respectively. The operator bool() function allows the Result to be used in a boolean context, such as an if statement. The unwrap() and err() member functions can be used to get the value contained in the Result, but will assert if the Result is not of the expected type. For parametrizing maybe_error with Ok without value, should be used template Ok, you can return just {} in this case as success. Co-Authored-By: Konstantin Akimov --- src/Makefile.am | 1 + src/util/result.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 src/util/result.h diff --git a/src/Makefile.am b/src/Makefile.am index a354b9e6f514..981c8928211d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -328,6 +328,7 @@ BITCOIN_CORE_H = \ util/overflow.h \ util/ranges.h \ util/readwritefile.h \ + util/result.h \ util/underlying.h \ util/serfloat.h \ util/settings.h \ diff --git a/src/util/result.h b/src/util/result.h new file mode 100644 index 000000000000..5641e75afca9 --- /dev/null +++ b/src/util/result.h @@ -0,0 +1,69 @@ +// Copyright (c) 2023 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_RESULT_H +#define BITCOIN_UTIL_RESULT_H + +#include +#include // for std::move() +#include + +template +struct Ok { + constexpr explicit Ok(T val) : val_(std::move(val)) {} + const T val_; +}; + +// Specialization of the Ok struct for void type +template<> +struct Ok { + constexpr Ok() = default; +}; + +template +struct Err { + constexpr explicit Err(E val) : val_(std::move(val)) {} + + template + constexpr explicit Err(Ts...t) : val_{t...} {} + + const E val_; +}; + +template +class Result { +public: + constexpr Result(Ok val) : result{val} {} + template + constexpr Result(Ts... t) : result{Ok{t...}} {} + constexpr Result(Err err) : result{err.val_} {} + + [[nodiscard]] constexpr bool is_ok() const { return std::holds_alternative>(result); } + [[nodiscard]] constexpr bool is_err() const { return !is_ok(); } + + [[nodiscard]] constexpr explicit operator bool() const { + return is_ok(); + } + + template + [[nodiscard]] constexpr const U& operator*() const { + return unwrap(); + } + + template + [[nodiscard]] constexpr const U& unwrap() const { + assert(is_ok()); + return std::get>(result).val_; + } + + [[nodiscard]] constexpr const E& err() const { + assert(is_err()); + return std::get(result); + } + +private: + std::variant, E> result; +}; + +#endif