rippled
Loading...
Searching...
No Matches
Expected.h
1#pragma once
2
3#include <xrpl/basics/contract.h>
4
5#include <boost/outcome.hpp>
6
7#include <stdexcept>
8
9namespace xrpl {
10
18// Exception thrown by an invalid access to Expected.
20{
21 bad_expected_access() : runtime_error("bad expected access")
22 {
23 }
24};
25
26namespace detail {
27
28// Custom policy for Expected. Always throw on an invalid access.
29struct throw_policy : public boost::outcome_v2::policy::base
30{
31 template <class Impl>
32 static constexpr void
33 wide_value_check(Impl&& self)
34 {
35 if (!base::_has_value(std::forward<Impl>(self)))
36 Throw<bad_expected_access>();
37 }
38
39 template <class Impl>
40 static constexpr void
41 wide_error_check(Impl&& self)
42 {
43 if (!base::_has_error(std::forward<Impl>(self)))
44 Throw<bad_expected_access>();
45 }
46
47 template <class Impl>
48 static constexpr void
50 {
51 if (!base::_has_exception(std::forward<Impl>(self)))
52 Throw<bad_expected_access>();
53 }
54};
55
56} // namespace detail
57
58// Definition of Unexpected, which is used to construct the unexpected
59// return type of an Expected.
60template <class E>
62{
63public:
64 static_assert(!std::is_same<E, void>::value, "E must not be void");
65
66 Unexpected() = delete;
67
68 constexpr explicit Unexpected(E const& e) : val_(e)
69 {
70 }
71
72 constexpr explicit Unexpected(E&& e) : val_(std::move(e))
73 {
74 }
75
76 constexpr E const&
77 value() const&
78 {
79 return val_;
80 }
81
82 constexpr E&
84 {
85 return val_;
86 }
87
88 constexpr E&&
89 value() &&
90 {
91 return std::move(val_);
92 }
93
94 constexpr E const&&
95 value() const&&
96 {
97 return std::move(val_);
98 }
99
100private:
102};
103
104// Unexpected deduction guide that converts array to const*.
105template <typename E, std::size_t N>
107
108// Definition of Expected. All of the machinery comes from boost::result.
109template <class T, class E>
110class [[nodiscard]] Expected : private boost::outcome_v2::result<T, E, detail::throw_policy>
111{
112 using Base = boost::outcome_v2::result<T, E, detail::throw_policy>;
113
114public:
115 template <typename U>
117 constexpr Expected(U&& r) : Base(boost::outcome_v2::in_place_type_t<T>{}, std::forward<U>(r))
118 {
119 }
120
121 template <typename U>
123 constexpr Expected(Unexpected<U> e) : Base(boost::outcome_v2::in_place_type_t<E>{}, std::move(e.value()))
124 {
125 }
126
127 constexpr bool
128 has_value() const
129 {
130 return Base::has_value();
131 }
132
133 constexpr T const&
134 value() const
135 {
136 return Base::value();
137 }
138
139 constexpr T&
141 {
142 return Base::value();
143 }
144
145 constexpr E const&
146 error() const
147 {
148 return Base::error();
149 }
150
151 constexpr E&
153 {
154 return Base::error();
155 }
156
157 constexpr explicit
158 operator bool() const
159 {
160 return has_value();
161 }
162
163 // Add operator* and operator-> so the Expected API looks a bit more like
164 // what std::expected is likely to look like. See:
165 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0323r10.html
166 [[nodiscard]] constexpr T&
168 {
169 return this->value();
170 }
171
172 [[nodiscard]] constexpr T const&
173 operator*() const
174 {
175 return this->value();
176 }
177
178 [[nodiscard]] constexpr T*
180 {
181 return &this->value();
182 }
183
184 [[nodiscard]] constexpr T const*
186 {
187 return &this->value();
188 }
189};
190
191// Specialization of Expected<void, E>. Allows returning either success
192// (without a value) or the reason for the failure.
193template <class E>
194class [[nodiscard]] Expected<void, E> : private boost::outcome_v2::result<void, E, detail::throw_policy>
195{
196 using Base = boost::outcome_v2::result<void, E, detail::throw_policy>;
197
198public:
199 // The default constructor makes a successful Expected<void, E>.
200 // This aligns with std::expected behavior proposed in P0323R10.
201 constexpr Expected() : Base(boost::outcome_v2::success())
202 {
203 }
204
205 template <typename U>
207 constexpr Expected(Unexpected<U> e) : Base(E(std::move(e.value())))
208 {
209 }
210
211 constexpr E const&
212 error() const
213 {
214 return Base::error();
215 }
216
217 constexpr E&
219 {
220 return Base::error();
221 }
222
223 constexpr explicit
224 operator bool() const
225 {
226 return Base::has_value();
227 }
228};
229
230} // namespace xrpl
boost::outcome_v2::result< void, E, detail::throw_policy > Base
Definition Expected.h:196
constexpr E & error()
Definition Expected.h:218
constexpr E const & error() const
Definition Expected.h:212
constexpr Expected(Unexpected< U > e)
Definition Expected.h:207
constexpr bool has_value() const
Definition Expected.h:128
constexpr T const & value() const
Definition Expected.h:134
constexpr Expected(U &&r)
Definition Expected.h:117
constexpr T const & operator*() const
Definition Expected.h:173
constexpr T & operator*()
Definition Expected.h:167
boost::outcome_v2::result< T, E, detail::throw_policy > Base
Definition Expected.h:112
constexpr T * operator->()
Definition Expected.h:179
constexpr E & error()
Definition Expected.h:152
constexpr T const * operator->() const
Definition Expected.h:185
constexpr Expected(Unexpected< U > e)
Definition Expected.h:123
constexpr T & value()
Definition Expected.h:140
constexpr E const & error() const
Definition Expected.h:146
constexpr E && value() &&
Definition Expected.h:89
constexpr E const & value() const &
Definition Expected.h:77
Unexpected()=delete
constexpr Unexpected(E &&e)
Definition Expected.h:72
constexpr E & value() &
Definition Expected.h:83
constexpr E const && value() const &&
Definition Expected.h:95
constexpr Unexpected(E const &e)
Definition Expected.h:68
T is_same_v
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
Expected is an approximation of std::expected (hoped for in C++23)
Definition Expected.h:20
static constexpr void wide_value_check(Impl &&self)
Definition Expected.h:33
static constexpr void wide_error_check(Impl &&self)
Definition Expected.h:41
static constexpr void wide_exception_check(Impl &&self)
Definition Expected.h:49