Bitcoin Core  31.0.0
P2P Digital Currency
expected.h
Go to the documentation of this file.
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 #include <util/check.h>
10 
11 #include <cassert>
12 #include <exception>
13 #include <utility>
14 #include <variant>
15 
16 namespace util {
17 
20 template <class E>
22 {
23 public:
24  constexpr explicit Unexpected(E e) : m_error(std::move(e)) {}
25 
26  constexpr const E& error() const& noexcept LIFETIMEBOUND { return m_error; }
27  constexpr E& error() & noexcept LIFETIMEBOUND { return m_error; }
28  constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(m_error); }
29 
30 private:
32 };
33 
34 struct BadExpectedAccess : std::exception {
35  const char* what() const noexcept override { return "Bad util::Expected access"; }
36 };
37 
43 template <class T, class E>
44 class Expected
45 {
46 private:
47  std::variant<T, E> m_data;
48 
49 public:
50  constexpr Expected() : m_data{std::in_place_index<0>, T{}} {}
51  constexpr Expected(T v) : m_data{std::in_place_index<0>, std::move(v)} {}
52  template <class Err>
53  constexpr Expected(Unexpected<Err> u) : m_data{std::in_place_index<1>, std::move(u).error()}
54  {
55  }
56 
57  constexpr bool has_value() const noexcept { return m_data.index() == 0; }
58  constexpr explicit operator bool() const noexcept { return has_value(); }
59 
60  constexpr const T& value() const& LIFETIMEBOUND
61  {
62  if (!has_value()) {
63  throw BadExpectedAccess{};
64  }
65  return std::get<0>(m_data);
66  }
67  constexpr T& value() & LIFETIMEBOUND
68  {
69  if (!has_value()) {
70  throw BadExpectedAccess{};
71  }
72  return std::get<0>(m_data);
73  }
74  constexpr T&& value() && LIFETIMEBOUND { return std::move(value()); }
75 
76  template <class U>
77  T value_or(U&& default_value) const&
78  {
79  return has_value() ? value() : std::forward<U>(default_value);
80  }
81  template <class U>
82  T value_or(U&& default_value) &&
83  {
84  return has_value() ? std::move(value()) : std::forward<U>(default_value);
85  }
86 
87  constexpr const E& error() const& noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
88  constexpr E& error() & noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
89  constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(error()); }
90 
91  constexpr void swap(Expected& other) noexcept { m_data.swap(other.m_data); }
92 
93  constexpr T& operator*() & noexcept LIFETIMEBOUND { return value(); }
94  constexpr const T& operator*() const& noexcept LIFETIMEBOUND { return value(); }
95  constexpr T&& operator*() && noexcept LIFETIMEBOUND { return std::move(value()); }
96 
97  constexpr T* operator->() noexcept LIFETIMEBOUND { return &value(); }
98  constexpr const T* operator->() const noexcept LIFETIMEBOUND { return &value(); }
99 };
100 
101 template <class E>
102 class Expected<void, E>
103 {
104 private:
105  std::variant<std::monostate, E> m_data;
106 
107 public:
108  constexpr Expected() : m_data{std::in_place_index<0>, std::monostate{}} {}
109  template <class Err>
110  constexpr Expected(Unexpected<Err> u) : m_data{std::in_place_index<1>, std::move(u).error()}
111  {
112  }
113 
114  constexpr bool has_value() const noexcept { return m_data.index() == 0; }
115  constexpr explicit operator bool() const noexcept { return has_value(); }
116 
117  constexpr void operator*() const noexcept { return value(); }
118  constexpr void value() const
119  {
120  if (!has_value()) {
121  throw BadExpectedAccess{};
122  }
123  }
124 
125  constexpr const E& error() const& noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
126  constexpr E& error() & noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
127  constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(error()); }
128 };
129 
130 } // namespace util
131 
132 #endif // BITCOIN_UTIL_EXPECTED_H
constexpr const T & value() const &LIFETIMEBOUND
Definition: expected.h:60
constexpr void operator*() const noexcept
Definition: expected.h:117
constexpr const T & operator*() const &noexcept LIFETIMEBOUND
Definition: expected.h:94
constexpr T & value() &LIFETIMEBOUND
Definition: expected.h:67
Definition: common.h:29
constexpr bool has_value() const noexcept
Definition: expected.h:114
constexpr E & error() &noexcept LIFETIMEBOUND
Definition: expected.h:27
constexpr T & operator*() &noexcept LIFETIMEBOUND
Definition: expected.h:93
constexpr Expected(Unexpected< Err > u)
Definition: expected.h:53
T value_or(U &&default_value) &&
Definition: expected.h:82
#define E
Definition: util_tests.cpp:562
constexpr E && error() &&noexcept LIFETIMEBOUND
Definition: expected.h:89
constexpr E & error() &noexcept LIFETIMEBOUND
Definition: expected.h:88
std::variant< std::monostate, E > m_data
Definition: expected.h:105
constexpr E && error() &&noexcept LIFETIMEBOUND
Definition: expected.h:127
The util::Unexpected class represents an unexpected value stored in util::Expected.
Definition: expected.h:21
#define LIFETIMEBOUND
Definition: attributes.h:16
constexpr void value() const
Definition: expected.h:118
const char * what() const noexcept override
Definition: expected.h:35
constexpr const E & error() const &noexcept LIFETIMEBOUND
Definition: expected.h:26
constexpr Unexpected(E e)
Definition: expected.h:24
std::variant< T, E > m_data
Definition: expected.h:47
constexpr Expected()
Definition: expected.h:50
constexpr Expected(Unexpected< Err > u)
Definition: expected.h:110
constexpr T * operator->() noexcept LIFETIMEBOUND
Definition: expected.h:97
constexpr const T * operator->() const noexcept LIFETIMEBOUND
Definition: expected.h:98
The util::Expected class provides a standard way for low-level functions to return either error value...
Definition: expected.h:44
constexpr const E & error() const &noexcept LIFETIMEBOUND
Definition: expected.h:87
constexpr Expected(T v)
Definition: expected.h:51
constexpr void swap(Expected &other) noexcept
Definition: expected.h:91
constexpr T && value() &&LIFETIMEBOUND
Definition: expected.h:74
T value_or(U &&default_value) const &
Definition: expected.h:77
constexpr E & error() &noexcept LIFETIMEBOUND
Definition: expected.h:126
constexpr bool has_value() const noexcept
Definition: expected.h:57
constexpr E && error() &&noexcept LIFETIMEBOUND
Definition: expected.h:28
constexpr T && operator*() &&noexcept LIFETIMEBOUND
Definition: expected.h:95
#define T(expected, seed, data)
constexpr const E & error() const &noexcept LIFETIMEBOUND
Definition: expected.h:125
#define Assert(val)
Identity function.
Definition: check.h:113