@@ -119,19 +119,19 @@ class Result {
119
119
120
120
// / Monadic operation - F must be a function of type T -> Result<U>.
121
121
template <class F >
122
- auto and_then (const F& _f) {
122
+ auto and_then (F&& _f) && {
123
123
// / Result_U is expected to be of type Result<U>.
124
124
using Result_U = typename std::invoke_result<F, T>::type;
125
125
if (success_) {
126
- return Result_U (_f (std::forward<T>( get_t () )));
126
+ return Result_U (_f (std::move (* this ). get_t ()));
127
127
} else {
128
- return Result_U (std::forward<Error>( get_err () ));
128
+ return Result_U (std::move (* this ). get_err ());
129
129
}
130
130
}
131
131
132
132
// / Monadic operation - F must be a function of type T -> Result<U>.
133
133
template <class F >
134
- auto and_then (const F& _f) const {
134
+ auto and_then (const F& _f) const & {
135
135
// / Result_U is expected to be of type Result<U>.
136
136
using Result_U = typename std::invoke_result<F, T>::type;
137
137
if (success_) {
@@ -146,11 +146,15 @@ class Result {
146
146
147
147
// / Allows access to the underlying value. Careful: Will result in undefined
148
148
// / behavior, if the result contains an error.
149
- T& operator *() noexcept { return get_t (); }
149
+ T&& operator *() && noexcept { return std::move (*this ).get_t (); }
150
+
151
+ // / Allows access to the underlying value. Careful: Will result in undefined
152
+ // / behavior, if the result contains an error.
153
+ T& operator *() & noexcept { return get_t (); }
150
154
151
155
// / Allows read access to the underlying value. Careful: Will result in
152
156
// / undefined behavior, if the result contains an error.
153
- const T& operator *() const noexcept { return get_t (); }
157
+ const T& operator *() const & noexcept { return get_t (); }
154
158
155
159
// / Assigns the underlying object.
156
160
Result<T>& operator =(const Result<T>& _other) {
@@ -180,6 +184,7 @@ class Result {
180
184
new (&get_err ()) Error (_err.error ());
181
185
return *this ;
182
186
}
187
+
183
188
Result<T>& operator =(const Unexpected<Error>& _err) noexcept {
184
189
destroy ();
185
190
success_ = false ;
@@ -199,18 +204,18 @@ class Result {
199
204
// / Expects a function that takes of type Error -> Result<T> and returns
200
205
// / Result<T>.
201
206
template <class F >
202
- Result<T> or_else (const F& _f) {
207
+ Result<T> or_else (const F& _f) && {
203
208
if (success_) {
204
- return std::forward<T>( get_t () );
209
+ return std::move (* this ). get_t ();
205
210
} else {
206
- return _f (std::forward<Error>( get_err () ));
211
+ return _f (std::move (* this ). get_err ());
207
212
}
208
213
}
209
214
210
215
// / Expects a function that takes of type Error -> Result<T> and returns
211
216
// / Result<T>.
212
217
template <class F >
213
- Result<T> or_else (const F& _f) const {
218
+ Result<T> or_else (const F& _f) const & {
214
219
if (success_) {
215
220
return get_t ();
216
221
} else {
@@ -220,19 +225,19 @@ class Result {
220
225
221
226
// / Functor operation - F must be a function of type T -> U.
222
227
template <class F >
223
- auto transform (const F& _f) {
228
+ auto transform (const F& _f) && {
224
229
// / Result_U is expected to be of type Result<U>.
225
- using U = typename std::invoke_result <F, T>::type ;
230
+ using U = std::invoke_result_t <F, T>;
226
231
if (success_) {
227
- return rfl::Result<U>(_f (std::forward<T>( get_t () )));
232
+ return rfl::Result<U>(_f (std::move (* this ). get_t ()));
228
233
} else {
229
- return rfl::Result<U>(rfl::Unexpected (std::forward<Error>( get_err () )));
234
+ return rfl::Result<U>(rfl::Unexpected (std::move (* this ). get_err ()));
230
235
}
231
236
}
232
237
233
238
// / Functor operation - F must be a function of type T -> U.
234
239
template <class F >
235
- auto transform (const F& _f) const {
240
+ auto transform (const F& _f) const & {
236
241
// / Result_U is expected to be of type Result<U>.
237
242
using U = typename std::invoke_result<F, T>::type;
238
243
if (success_) {
@@ -244,17 +249,17 @@ class Result {
244
249
245
250
// / Returns the value if the result does not contain an error, throws an
246
251
// / exceptions if not. Similar to .unwrap() in Rust.
247
- T& value () {
252
+ T&& value() && {
248
253
if (success_) {
249
- return get_t ();
254
+ return std::move (* this ). get_t ();
250
255
} else {
251
256
throw std::runtime_error (get_err ().what ());
252
257
}
253
258
}
254
259
255
260
// / Returns the value if the result does not contain an error, throws an
256
261
// / exceptions if not. Similar to .unwrap() in Rust.
257
- const T& value () const {
262
+ const T& value () const & {
258
263
if (success_) {
259
264
return get_t ();
260
265
} else {
@@ -263,64 +268,72 @@ class Result {
263
268
}
264
269
265
270
// / Returns the value or a default.
266
- T value_or (T&& _default) noexcept {
271
+ T&& value_or(T&& _default) && noexcept {
267
272
if (success_) {
268
- return std::forward<T>( get_t () );
273
+ return std::move (* this ). get_t ();
269
274
} else {
270
275
return std::forward<T>(_default);
271
276
}
272
277
}
273
278
274
279
// / Returns the value or a default.
275
- T value_or (const T& _default) const noexcept {
280
+ T value_or (const T& _default) const & noexcept {
276
281
if (success_) {
277
282
return get_t ();
278
283
} else {
279
284
return _default;
280
285
}
281
286
}
282
287
283
- // As specified by the standard :
284
- // https://en.cppreference.com/w/cpp/utility/expected
285
- // Observers
286
288
template <class G = rfl::Error>
287
- rfl::Error error_or (G&& _default) const & {
289
+ rfl::Error error_or (G&& _default) & & {
288
290
if (success_) {
289
- return _default;
291
+ return std::forward<G>( _default) ;
290
292
} else {
291
- return get_err ();
293
+ return std::move (* this ). get_err ();
292
294
}
293
295
}
296
+
297
+ // As specified by the standard :
298
+ // https://en.cppreference.com/w/cpp/utility/expected
299
+ // Observers
294
300
template <class G = rfl::Error>
295
- rfl::Error error_or (G&& _default) & & {
301
+ rfl::Error error_or (G&& _default) const & {
296
302
if (success_) {
297
- return _default;
303
+ return std::forward<G>( _default) ;
298
304
} else {
299
305
return get_err ();
300
306
}
301
307
}
308
+
302
309
bool has_value () const noexcept { return success_; }
310
+
303
311
const Error& error () const & {
304
312
if (success_) throw std::runtime_error (" Expected does not contain value" );
305
313
return get_err ();
306
314
}
307
- Error& error () & {
315
+
316
+ Error& error () && {
308
317
if (success_) throw std::runtime_error (" Expected does not contain value" );
309
- return get_err ();
318
+ return std::move (* this ). get_err ();
310
319
}
320
+
311
321
T* operator ->() noexcept { return &get_t (); }
322
+
312
323
const T* operator ->() const noexcept { return &get_t (); }
324
+
313
325
template <class F >
314
326
rfl::Result<T> transform_error (F&& f) && {
315
327
static_assert (
316
328
std::is_same<std::invoke_result_t <F, rfl::Error>, rfl::Error>(),
317
329
" A function passed to transform_error must return an error." );
318
330
if (!has_value ()) {
319
- return rfl::Result<T>{std::invoke (f, std::move (get_err () ))};
331
+ return rfl::Result<T>{std::invoke (f, std::move (* this ). get_err ())};
320
332
} else {
321
- return rfl::Result<T>{std::move (value () )};
333
+ return rfl::Result<T>{std::move (* this ). value ()};
322
334
}
323
335
}
336
+
324
337
template <class F >
325
338
rfl::Result<T> transform_error (F&& f) const & {
326
339
static_assert (
@@ -352,19 +365,27 @@ class Result {
352
365
}
353
366
}
354
367
355
- T& get_t () noexcept {
368
+ T&& get_t () && noexcept {
369
+ return std::move (*std::launder (reinterpret_cast <T*>(t_or_err_.data ())));
370
+ }
371
+
372
+ T& get_t () & noexcept {
356
373
return *std::launder (reinterpret_cast <T*>(t_or_err_.data ()));
357
374
}
358
375
359
- const T& get_t () const noexcept {
376
+ const T& get_t () const & noexcept {
360
377
return *std::launder (reinterpret_cast <const T*>(t_or_err_.data ()));
361
378
}
362
379
363
- Error& get_err () noexcept {
380
+ Error&& get_err() && noexcept {
381
+ return std::move (*std::launder (reinterpret_cast <Error*>(t_or_err_.data ())));
382
+ }
383
+
384
+ Error& get_err () & noexcept {
364
385
return *std::launder (reinterpret_cast <Error*>(t_or_err_.data ()));
365
386
}
366
387
367
- const Error& get_err () const noexcept {
388
+ const Error& get_err () const & noexcept {
368
389
return *std::launder (reinterpret_cast <const Error*>(t_or_err_.data ()));
369
390
}
370
391
0 commit comments