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