Branch data Line data Source code
1 : : // Copyright (c) The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or https://opensource.org/license/mit.
4 : :
5 : : #ifndef BITCOIN_UTIL_EXPECTED_H
6 : : #define BITCOIN_UTIL_EXPECTED_H
7 : :
8 : : #include <attributes.h>
9 : :
10 : : #include <cassert>
11 : : #include <type_traits>
12 : : #include <utility>
13 : : #include <variant>
14 : :
15 : : namespace util {
16 : :
17 : : /// The util::Unexpected class represents an unexpected value stored in
18 : : /// util::Expected.
19 : : template <class E>
20 : : class Unexpected
21 : : {
22 : : public:
23 : : constexpr explicit Unexpected(E e) : err(std::move(e)) {}
24 : : E err;
25 : : };
26 : :
27 : : /// The util::Expected class provides a standard way for low-level functions to
28 : : /// return either error values or result values.
29 : : ///
30 : : /// It provides a smaller version of std::expected from C++23. Missing features
31 : : /// can be added, if needed.
32 : : template <class T, class E>
33 : 0 : class Expected
34 : : {
35 : : private:
36 : : using ValueType = std::conditional_t<std::is_same_v<T, void>, std::monostate, T>;
37 : : std::variant<ValueType, E> m_data;
38 : :
39 : : public:
40 : : constexpr Expected() : m_data{std::in_place_index_t<0>{}, ValueType{}} {}
41 : : constexpr Expected(ValueType v) : m_data{std::in_place_index_t<0>{}, std::move(v)} {}
42 : : template <class Err>
43 [ # # # # : 0 : constexpr Expected(Unexpected<Err> u) : m_data{std::in_place_index_t<1>{}, std::move(u.err)}
# # # # ]
44 : : {
45 : 0 : }
46 : :
47 : 0 : constexpr bool has_value() const noexcept { return m_data.index() == 0; }
48 [ # # ]: 0 : constexpr explicit operator bool() const noexcept { return has_value(); }
49 : :
50 : : constexpr const ValueType& value() const LIFETIMEBOUND
51 : : {
52 : : assert(has_value());
53 : : return std::get<0>(m_data);
54 : : }
55 : : constexpr ValueType& value() LIFETIMEBOUND
56 : : {
57 : : assert(has_value());
58 : : return std::get<0>(m_data);
59 : : }
60 : :
61 : : template <class U>
62 : : ValueType value_or(U&& default_value) const&
63 : : {
64 : : return has_value() ? value() : std::forward<U>(default_value);
65 : : }
66 : : template <class U>
67 : : ValueType value_or(U&& default_value) &&
68 : : {
69 : : return has_value() ? std::move(value()) : std::forward<U>(default_value);
70 : : }
71 : :
72 [ # # ]: 0 : constexpr const E& error() const LIFETIMEBOUND
73 : : {
74 [ # # ]: 0 : assert(!has_value());
75 [ # # ]: 0 : return std::get<1>(m_data);
76 : : }
77 : : constexpr E& error() LIFETIMEBOUND
78 : : {
79 : : assert(!has_value());
80 : : return std::get<1>(m_data);
81 : : }
82 : :
83 : : constexpr ValueType& operator*() LIFETIMEBOUND { return value(); }
84 : : constexpr const ValueType& operator*() const LIFETIMEBOUND { return value(); }
85 : :
86 : : constexpr ValueType* operator->() LIFETIMEBOUND { return &value(); }
87 : : constexpr const ValueType* operator->() const LIFETIMEBOUND { return &value(); }
88 : : };
89 : :
90 : : } // namespace util
91 : :
92 : : #endif // BITCOIN_UTIL_EXPECTED_H
|