1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /**
18 * Like folly::Optional, but can store a value *or* an error.
19 *
20 * @author Eric Niebler (eniebler@fb.com)
21 */
22
23 #pragma once
24
25 #include <cstddef>
26 #include <initializer_list>
27 #include <new>
28 #include <stdexcept>
29 #include <type_traits>
30 #include <utility>
31
32 #include <folly/CPortability.h>
33 #include <folly/CppAttributes.h>
34 #include <folly/Likely.h>
35 #include <folly/Optional.h>
36 #include <folly/Portability.h>
37 #include <folly/Preprocessor.h>
38 #include <folly/Traits.h>
39 #include <folly/Unit.h>
40 #include <folly/Utility.h>
41 #include <folly/lang/Exception.h>
42
43 #define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__)
44
45 #define FOLLY_REQUIRES_IMPL(...) \
46 bool FOLLY_EXPECTED_ID(Requires) = false, \
47 typename std::enable_if< \
48 (FOLLY_EXPECTED_ID(Requires) || static_cast<bool>(__VA_ARGS__)), \
49 int>::type = 0
50
51 #define FOLLY_REQUIRES_TRAILING(...) , FOLLY_REQUIRES_IMPL(__VA_ARGS__)
52
53 #define FOLLY_REQUIRES(...) template <FOLLY_REQUIRES_IMPL(__VA_ARGS__)>
54
55 namespace folly {
56
57 /**
58 * Forward declarations
59 */
60 template <class Error>
61 class Unexpected;
62
63 template <class Error>
64 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(Error&&);
65
66 template <class Value, class Error>
67 class Expected;
68
69 template <class Error, class Value>
70 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
71 Value&&);
72
73 /**
74 * Alias for an Expected type's associated value_type
75 */
76 template <class Expected>
77 using ExpectedValueType =
78 typename std::remove_reference<Expected>::type::value_type;
79
80 /**
81 * Alias for an Expected type's associated error_type
82 */
83 template <class Expected>
84 using ExpectedErrorType =
85 typename std::remove_reference<Expected>::type::error_type;
86
87 // Details...
88 namespace expected_detail {
89
90 template <typename Value, typename Error>
91 struct Promise;
92 template <typename Value, typename Error>
93 struct PromiseReturn;
94
95 template <template <class...> class Trait, class... Ts>
96 using StrictAllOf = StrictConjunction<Trait<Ts>...>;
97
98 template <class T>
99 using IsCopyable = StrictConjunction<
100 std::is_copy_constructible<T>,
101 std::is_copy_assignable<T>>;
102
103 template <class T>
104 using IsMovable = StrictConjunction<
105 std::is_move_constructible<T>,
106 std::is_move_assignable<T>>;
107
108 template <class T>
109 using IsNothrowCopyable = StrictConjunction<
110 std::is_nothrow_copy_constructible<T>,
111 std::is_nothrow_copy_assignable<T>>;
112
113 template <class T>
114 using IsNothrowMovable = StrictConjunction<
115 std::is_nothrow_move_constructible<T>,
116 std::is_nothrow_move_assignable<T>>;
117
118 template <class From, class To>
119 using IsConvertible = StrictConjunction<
120 std::is_constructible<To, From>,
121 std::is_assignable<To&, From>>;
122
123 template <class T, class U>
124 auto doEmplaceAssign(int, T& t, U&& u)
125 -> decltype(void(t = static_cast<U&&>(u))) {
126 t = static_cast<U&&>(u);
127 }
128
129 template <class T, class U>
130 auto doEmplaceAssign(long, T& t, U&& u)
131 -> decltype(void(T(static_cast<U&&>(u)))) {
132 t.~T();
133 ::new ((void*)std::addressof(t)) T(static_cast<U&&>(u));
134 }
135
136 template <class T, class... Us>
137 auto doEmplaceAssign(int, T& t, Us&&... us)
138 -> decltype(void(t = T(static_cast<Us&&>(us)...))) {
139 t = T(static_cast<Us&&>(us)...);
140 }
141
142 template <class T, class... Us>
143 auto doEmplaceAssign(long, T& t, Us&&... us)
144 -> decltype(void(T(static_cast<Us&&>(us)...))) {
145 t.~T();
146 ::new ((void*)std::addressof(t)) T(static_cast<Us&&>(us)...);
147 }
148
149 struct EmptyTag {};
150 struct ValueTag {};
151 struct ErrorTag {};
152 enum class Which : unsigned char { eEmpty, eValue, eError };
153 enum class StorageType { ePODStruct, ePODUnion, eUnion };
154
155 template <class Value, class Error>
getStorageType()156 constexpr StorageType getStorageType() {
157 return StrictAllOf<is_trivially_copyable, Value, Error>::value
158 ? (sizeof(std::pair<Value, Error>) <= sizeof(void* [2]) &&
159 StrictAllOf<std::is_trivial, Value, Error>::value
160 ? StorageType::ePODStruct
161 : StorageType::ePODUnion)
162 : StorageType::eUnion;
163 }
164
165 template <
166 class Value,
167 class Error,
168 StorageType = expected_detail::getStorageType<Value, Error>()> // ePODUnion
169 struct ExpectedStorage {
170 using value_type = Value;
171 using error_type = Error;
172 union {
173 Value value_;
174 Error error_;
175 char ch_;
176 };
177 Which which_;
178
179 template <class E = Error, class = decltype(E{})>
ExpectedStorageExpectedStorage180 constexpr ExpectedStorage() noexcept(noexcept(E{}))
181 : error_{}, which_(Which::eError) {}
ExpectedStorageExpectedStorage182 explicit constexpr ExpectedStorage(EmptyTag) noexcept
183 : ch_{}, which_(Which::eEmpty) {}
184 template <class... Vs>
ExpectedStorageExpectedStorage185 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
186 noexcept(Value(static_cast<Vs&&>(vs)...)))
187 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
188 template <class... Es>
ExpectedStorageExpectedStorage189 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
190 noexcept(Error(static_cast<Es&&>(es)...)))
191 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
clearExpectedStorage192 void clear() noexcept {}
uninitializedByExceptionExpectedStorage193 static constexpr bool uninitializedByException() noexcept {
194 // Although which_ may temporarily be eEmpty during construction, it
195 // is always either eValue or eError for a fully-constructed Expected.
196 return false;
197 }
198 template <class... Vs>
assignValueExpectedStorage199 void assignValue(Vs&&... vs) {
200 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
201 which_ = Which::eValue;
202 }
203 template <class... Es>
assignErrorExpectedStorage204 void assignError(Es&&... es) {
205 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
206 which_ = Which::eError;
207 }
208 template <class Other>
assignExpectedStorage209 void assign(Other&& that) {
210 switch (that.which_) {
211 case Which::eValue:
212 this->assignValue(static_cast<Other&&>(that).value());
213 break;
214 case Which::eError:
215 this->assignError(static_cast<Other&&>(that).error());
216 break;
217 case Which::eEmpty:
218 default:
219 this->clear();
220 break;
221 }
222 }
valueExpectedStorage223 Value& value() & { return value_; }
valueExpectedStorage224 const Value& value() const& { return value_; }
valueExpectedStorage225 Value&& value() && { return std::move(value_); }
errorExpectedStorage226 Error& error() & { return error_; }
errorExpectedStorage227 const Error& error() const& { return error_; }
errorExpectedStorage228 Error&& error() && { return std::move(error_); }
229 };
230
231 template <class Value, class Error>
232 struct ExpectedUnion {
233 union {
234 Value value_;
235 Error error_;
236 char ch_{};
237 };
238 Which which_ = Which::eEmpty;
239
ExpectedUnionExpectedUnion240 explicit constexpr ExpectedUnion(EmptyTag) noexcept {}
241 template <class... Vs>
ExpectedUnionExpectedUnion242 explicit constexpr ExpectedUnion(ValueTag, Vs&&... vs) noexcept(
243 noexcept(Value(static_cast<Vs&&>(vs)...)))
244 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
245 template <class... Es>
ExpectedUnionExpectedUnion246 explicit constexpr ExpectedUnion(ErrorTag, Es&&... es) noexcept(
247 noexcept(Error(static_cast<Es&&>(es)...)))
248 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
ExpectedUnionExpectedUnion249 ExpectedUnion(const ExpectedUnion&) {}
ExpectedUnionExpectedUnion250 ExpectedUnion(ExpectedUnion&&) noexcept {}
251 ExpectedUnion& operator=(const ExpectedUnion&) { return *this; }
252 ExpectedUnion& operator=(ExpectedUnion&&) noexcept { return *this; }
~ExpectedUnionExpectedUnion253 ~ExpectedUnion() {}
valueExpectedUnion254 Value& value() & { return value_; }
valueExpectedUnion255 const Value& value() const& { return value_; }
valueExpectedUnion256 Value&& value() && { return std::move(value_); }
errorExpectedUnion257 Error& error() & { return error_; }
errorExpectedUnion258 const Error& error() const& { return error_; }
errorExpectedUnion259 Error&& error() && { return std::move(error_); }
260 };
261
262 template <class Derived, bool, bool Noexcept>
263 struct CopyConstructible {
264 constexpr CopyConstructible() = default;
noexceptCopyConstructible265 CopyConstructible(const CopyConstructible& that) noexcept(Noexcept) {
266 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
267 }
268 constexpr CopyConstructible(CopyConstructible&&) = default;
269 CopyConstructible& operator=(const CopyConstructible&) = default;
270 CopyConstructible& operator=(CopyConstructible&&) = default;
271 };
272
273 template <class Derived, bool Noexcept>
274 struct CopyConstructible<Derived, false, Noexcept> {
275 constexpr CopyConstructible() = default;
276 CopyConstructible(const CopyConstructible&) = delete;
277 constexpr CopyConstructible(CopyConstructible&&) = default;
278 CopyConstructible& operator=(const CopyConstructible&) = default;
279 CopyConstructible& operator=(CopyConstructible&&) = default;
280 };
281
282 template <class Derived, bool, bool Noexcept>
283 struct MoveConstructible {
284 constexpr MoveConstructible() = default;
285 constexpr MoveConstructible(const MoveConstructible&) = default;
286 MoveConstructible(MoveConstructible&& that) noexcept(Noexcept) {
287 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
288 }
289 MoveConstructible& operator=(const MoveConstructible&) = default;
290 MoveConstructible& operator=(MoveConstructible&&) = default;
291 };
292
293 template <class Derived, bool Noexcept>
294 struct MoveConstructible<Derived, false, Noexcept> {
295 constexpr MoveConstructible() = default;
296 constexpr MoveConstructible(const MoveConstructible&) = default;
297 MoveConstructible(MoveConstructible&&) = delete;
298 MoveConstructible& operator=(const MoveConstructible&) = default;
299 MoveConstructible& operator=(MoveConstructible&&) = default;
300 };
301
302 template <class Derived, bool, bool Noexcept>
303 struct CopyAssignable {
304 constexpr CopyAssignable() = default;
305 constexpr CopyAssignable(const CopyAssignable&) = default;
306 constexpr CopyAssignable(CopyAssignable&&) = default;
307 CopyAssignable& operator=(const CopyAssignable& that) noexcept(Noexcept) {
308 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
309 return *this;
310 }
311 CopyAssignable& operator=(CopyAssignable&&) = default;
312 };
313
314 template <class Derived, bool Noexcept>
315 struct CopyAssignable<Derived, false, Noexcept> {
316 constexpr CopyAssignable() = default;
317 constexpr CopyAssignable(const CopyAssignable&) = default;
318 constexpr CopyAssignable(CopyAssignable&&) = default;
319 CopyAssignable& operator=(const CopyAssignable&) = delete;
320 CopyAssignable& operator=(CopyAssignable&&) = default;
321 };
322
323 template <class Derived, bool, bool Noexcept>
324 struct MoveAssignable {
325 constexpr MoveAssignable() = default;
326 constexpr MoveAssignable(const MoveAssignable&) = default;
327 constexpr MoveAssignable(MoveAssignable&&) = default;
328 MoveAssignable& operator=(const MoveAssignable&) = default;
329 MoveAssignable& operator=(MoveAssignable&& that) noexcept(Noexcept) {
330 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
331 return *this;
332 }
333 };
334
335 template <class Derived, bool Noexcept>
336 struct MoveAssignable<Derived, false, Noexcept> {
337 constexpr MoveAssignable() = default;
338 constexpr MoveAssignable(const MoveAssignable&) = default;
339 constexpr MoveAssignable(MoveAssignable&&) = default;
340 MoveAssignable& operator=(const MoveAssignable&) = default;
341 MoveAssignable& operator=(MoveAssignable&& that) = delete;
342 };
343
344 template <class Value, class Error>
345 struct ExpectedStorage<Value, Error, StorageType::eUnion>
346 : ExpectedUnion<Value, Error>,
347 CopyConstructible<
348 ExpectedStorage<Value, Error, StorageType::eUnion>,
349 StrictAllOf<std::is_copy_constructible, Value, Error>::value,
350 StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::value>,
351 MoveConstructible<
352 ExpectedStorage<Value, Error, StorageType::eUnion>,
353 StrictAllOf<std::is_move_constructible, Value, Error>::value,
354 StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::value>,
355 CopyAssignable<
356 ExpectedStorage<Value, Error, StorageType::eUnion>,
357 StrictAllOf<IsCopyable, Value, Error>::value,
358 StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
359 MoveAssignable<
360 ExpectedStorage<Value, Error, StorageType::eUnion>,
361 StrictAllOf<IsMovable, Value, Error>::value,
362 StrictAllOf<IsNothrowMovable, Value, Error>::value> {
363 using value_type = Value;
364 using error_type = Error;
365 using Base = ExpectedUnion<Value, Error>;
366 template <class E = Error, class = decltype(E{})>
367 constexpr ExpectedStorage() noexcept(noexcept(E{})) : Base{ErrorTag{}} {}
368 ExpectedStorage(const ExpectedStorage&) = default;
369 ExpectedStorage(ExpectedStorage&&) = default;
370 ExpectedStorage& operator=(const ExpectedStorage&) = default;
371 ExpectedStorage& operator=(ExpectedStorage&&) = default;
372 using ExpectedUnion<Value, Error>::ExpectedUnion;
373 ~ExpectedStorage() { clear(); }
374 void clear() noexcept {
375 switch (this->which_) {
376 case Which::eValue:
377 this->value().~Value();
378 break;
379 case Which::eError:
380 this->error().~Error();
381 break;
382 case Which::eEmpty:
383 default:
384 break;
385 }
386 this->which_ = Which::eEmpty;
387 }
388 bool uninitializedByException() const noexcept {
389 return this->which_ == Which::eEmpty;
390 }
391 template <class... Vs>
392 void assignValue(Vs&&... vs) {
393 if (this->which_ == Which::eValue) {
394 expected_detail::doEmplaceAssign(
395 0, this->value(), static_cast<Vs&&>(vs)...);
396 } else {
397 this->clear();
398 ::new ((void*)std::addressof(this->value()))
399 Value(static_cast<Vs&&>(vs)...);
400 this->which_ = Which::eValue;
401 }
402 }
403 template <class... Es>
404 void assignError(Es&&... es) {
405 if (this->which_ == Which::eError) {
406 expected_detail::doEmplaceAssign(
407 0, this->error(), static_cast<Es&&>(es)...);
408 } else {
409 this->clear();
410 ::new ((void*)std::addressof(this->error()))
411 Error(static_cast<Es&&>(es)...);
412 this->which_ = Which::eError;
413 }
414 }
415 bool isSelfAssign(const ExpectedStorage* that) const { return this == that; }
416 constexpr bool isSelfAssign(const void*) const { return false; }
417 template <class Other>
418 void assign(Other&& that) {
419 if (isSelfAssign(&that)) {
420 return;
421 }
422 switch (that.which_) {
423 case Which::eValue:
424 this->assignValue(static_cast<Other&&>(that).value());
425 break;
426 case Which::eError:
427 this->assignError(static_cast<Other&&>(that).error());
428 break;
429 case Which::eEmpty:
430 default:
431 this->clear();
432 break;
433 }
434 }
435 };
436
437 // For small (pointer-sized) trivial types, a struct is faster than a union.
438 template <class Value, class Error>
439 struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
440 using value_type = Value;
441 using error_type = Error;
442 Which which_;
443 Error error_;
444 Value value_;
445
446 constexpr ExpectedStorage() noexcept
447 : which_(Which::eError), error_{}, value_{} {}
448 explicit constexpr ExpectedStorage(EmptyTag) noexcept
449 : which_(Which::eEmpty), error_{}, value_{} {}
450 template <class... Vs>
451 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
452 noexcept(Value(static_cast<Vs&&>(vs)...)))
453 : which_(Which::eValue), error_{}, value_(static_cast<Vs&&>(vs)...) {}
454 template <class... Es>
455 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
456 noexcept(Error(static_cast<Es&&>(es)...)))
457 : which_(Which::eError), error_(static_cast<Es&&>(es)...), value_{} {}
458 void clear() noexcept {}
459 constexpr static bool uninitializedByException() noexcept { return false; }
460 template <class... Vs>
461 void assignValue(Vs&&... vs) {
462 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
463 which_ = Which::eValue;
464 }
465 template <class... Es>
466 void assignError(Es&&... es) {
467 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
468 which_ = Which::eError;
469 }
470 template <class Other>
471 void assign(Other&& that) {
472 switch (that.which_) {
473 case Which::eValue:
474 this->assignValue(static_cast<Other&&>(that).value());
475 break;
476 case Which::eError:
477 this->assignError(static_cast<Other&&>(that).error());
478 break;
479 case Which::eEmpty:
480 default:
481 this->clear();
482 break;
483 }
484 }
485 Value& value() & { return value_; }
486 const Value& value() const& { return value_; }
487 Value&& value() && { return std::move(value_); }
488 Error& error() & { return error_; }
489 const Error& error() const& { return error_; }
490 Error&& error() && { return std::move(error_); }
491 };
492
493 namespace expected_detail_ExpectedHelper {
494 // Tricky hack so that Expected::then can handle lambdas that return void
495 template <class T>
496 inline T&& operator,(T&& t, Unit) noexcept {
497 return static_cast<T&&>(t);
498 }
499
500 struct ExpectedHelper {
501 template <class Error, class T>
502 static constexpr Expected<typename std::decay<T>::type, Error> return_(
503 T&& t) {
504 return folly::makeExpected<Error>(static_cast<T&&>(t));
505 }
506
507 template <
508 class Error,
509 class T,
510 class U FOLLY_REQUIRES_TRAILING(
511 expected_detail::IsConvertible<U&&, Error>::value)>
512 static constexpr Expected<T, Error> return_(Expected<T, U>&& t) {
513 return Expected<T, Error>(static_cast<Expected<T, U>&&>(t));
514 }
515
516 template <class This>
517 static typename std::decay<This>::type then_(This&& ex) {
518 return static_cast<This&&>(ex);
519 }
520
521 FOLLY_PUSH_WARNING
522 // Don't warn about not using the overloaded comma operator.
523 FOLLY_MSVC_DISABLE_WARNING(4913)
524 template <
525 class This,
526 class Fn,
527 class... Fns,
528 class E = ExpectedErrorType<This>,
529 class T = ExpectedHelper>
530 static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
531 T::template return_<E>(
532 (std::declval<Fn>()(std::declval<This>().value()), unit)),
533 std::declval<Fns>()...)) {
534 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
535 return T::then_(
536 T::template return_<E>(
537 // Uses the comma operator defined above IFF the lambda
538 // returns non-void.
539 (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
540 static_cast<Fns&&>(fns)...);
541 }
542 return makeUnexpected(static_cast<This&&>(ex).error());
543 }
544
545 template <
546 class This,
547 class Yes,
548 class No,
549 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
550 class Err = decltype(std::declval<No>()(std::declval<This>().error()))
551 FOLLY_REQUIRES_TRAILING(!std::is_void<Err>::value)>
552 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
553 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
554 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
555 }
556 throw_exception(static_cast<No&&>(no)(static_cast<This&&>(ex).error()));
557 }
558
559 template <
560 class This,
561 class Yes,
562 class No,
563 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
564 class Err = decltype(std::declval<No>()(std::declval<This&>().error()))
565 FOLLY_REQUIRES_TRAILING(std::is_void<Err>::value)>
566 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
567 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
568 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
569 }
570 static_cast<No&&>(no)(ex.error());
571 typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess bad;
572 throw_exception(bad(static_cast<This&&>(ex).error()));
573 }
574 FOLLY_POP_WARNING
575 };
576 } // namespace expected_detail_ExpectedHelper
577 /* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
578
579 struct UnexpectedTag {};
580
581 } // namespace expected_detail
582
583 using unexpected_t =
584 expected_detail::UnexpectedTag (&)(expected_detail::UnexpectedTag);
585
586 inline expected_detail::UnexpectedTag unexpected(
587 expected_detail::UnexpectedTag = {}) {
588 return {};
589 }
590
591 /**
592 * An exception type thrown by Expected on catastrophic logic errors.
593 */
594 class FOLLY_EXPORT BadExpectedAccess : public std::logic_error {
595 public:
596 BadExpectedAccess() : std::logic_error("bad Expected access") {}
597 };
598
599 namespace expected_detail {
600 // empty
601 } // namespace expected_detail
602
603 /**
604 * Unexpected - a helper type used to disambiguate the construction of
605 * Expected objects in the error state.
606 */
607 template <class Error>
608 class Unexpected final {
609 template <class E>
610 friend class Unexpected;
611 template <class V, class E>
612 friend class Expected;
613 friend struct expected_detail::ExpectedHelper;
614
615 public:
616 /**
617 * Unexpected::BadExpectedAccess - An exception type thrown by Expected
618 * when the user tries to access the nested value but the Expected object is
619 * actually storing an error code.
620 */
621 class FOLLY_EXPORT BadExpectedAccess : public folly::BadExpectedAccess {
622 public:
623 explicit BadExpectedAccess(Error err)
624 : folly::BadExpectedAccess{}, error_(std::move(err)) {}
625 /**
626 * The error code that was held by the Expected object when the user
627 * erroneously requested the value.
628 */
629 Error error() const { return error_; }
630
631 private:
632 Error error_;
633 };
634
635 /**
636 * Constructors
637 */
638 Unexpected() = default;
639 Unexpected(const Unexpected&) = default;
640 Unexpected(Unexpected&&) = default;
641 Unexpected& operator=(const Unexpected&) = default;
642 Unexpected& operator=(Unexpected&&) = default;
643 FOLLY_COLD constexpr /* implicit */ Unexpected(const Error& err)
644 : error_(err) {}
645 FOLLY_COLD constexpr /* implicit */ Unexpected(Error&& err)
646 : error_(std::move(err)) {}
647
648 template <class Other FOLLY_REQUIRES_TRAILING(
649 std::is_constructible<Error, Other&&>::value)>
650 constexpr /* implicit */ Unexpected(Unexpected<Other> that)
651 : error_(std::move(that.error())) {}
652
653 /**
654 * Assignment
655 */
656 template <class Other FOLLY_REQUIRES_TRAILING(
657 std::is_assignable<Error&, Other&&>::value)>
658 Unexpected& operator=(Unexpected<Other> that) {
659 error_ = std::move(that.error());
660 }
661
662 /**
663 * Observers
664 */
665 Error& error() & { return error_; }
666 const Error& error() const& { return error_; }
667 Error&& error() && { return std::move(error_); }
668
669 private:
670 struct MakeBadExpectedAccess {
671 template <class E>
672 BadExpectedAccess operator()(E&& err) const {
673 return BadExpectedAccess(static_cast<E&&>(err));
674 }
675 };
676
677 Error error_;
678 };
679
680 template <
681 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
682 inline bool operator==(
683 const Unexpected<Error>& lhs, const Unexpected<Error>& rhs) {
684 return lhs.error() == rhs.error();
685 }
686
687 template <
688 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
689 inline bool operator!=(
690 const Unexpected<Error>& lhs, const Unexpected<Error>& rhs) {
691 return !(lhs == rhs);
692 }
693
694 /**
695 * For constructing an Unexpected object from an error code. Unexpected objects
696 * are implicitly convertible to Expected object in the error state. Usage is
697 * as follows:
698 *
699 * enum class MyErrorCode { BAD_ERROR, WORSE_ERROR };
700 * Expected<int, MyErrorCode> myAPI() {
701 * int i = // ...;
702 * return i ? makeExpected<MyErrorCode>(i)
703 * : makeUnexpected(MyErrorCode::BAD_ERROR);
704 * }
705 */
706 template <class Error>
707 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(
708 Error&& err) {
709 return Unexpected<typename std::decay<Error>::type>{
710 static_cast<Error&&>(err)};
711 }
712
713 /**
714 * Expected - For holding a value or an error. Useful as an alternative to
715 * exceptions, for APIs where throwing on failure would be too expensive.
716 *
717 * Expected<Value, Error> is a variant over the types Value and Error.
718 *
719 * Expected does not offer support for references. Use
720 * Expected<std::reference_wrapper<T>, Error> if your API needs to return a
721 * reference or an error.
722 *
723 * Expected offers a continuation-based interface to reduce the boilerplate
724 * of checking error codes. The Expected::then member function takes a lambda
725 * that is to execute should the Expected object contain a value. The return
726 * value of the lambda is wrapped in an Expected and returned. If the lambda is
727 * not executed because the Expected contains an error, the error is returned
728 * immediately in a new Expected object.
729 *
730 * Expected<int, Error> funcTheFirst();
731 * Expected<std::string, Error> funcTheSecond() {
732 * return funcTheFirst().then([](int i) { return std::to_string(i); });
733 * }
734 *
735 * The above line of code could more verbosely written as:
736 *
737 * Expected<std::string, Error> funcTheSecond() {
738 * if (auto ex = funcTheFirst()) {
739 * return std::to_string(*ex);
740 * }
741 * return makeUnexpected(ex.error());
742 * }
743 *
744 * Continuations can chain, like:
745 *
746 * Expected<D, Error> maybeD = someFunc()
747 * .then([](A a){return B(a);})
748 * .then([](B b){return C(b);})
749 * .then([](C c){return D(c);});
750 *
751 * To avoid the redundant error checking that would happen if a call at the
752 * front of the chain returns an error, these call chains can be collaped into
753 * a single call to .then:
754 *
755 * Expected<D, Error> maybeD = someFunc()
756 * .then([](A a){return B(a);},
757 * [](B b){return C(b);},
758 * [](C c){return D(c);});
759 *
760 * The result of .then() is wrapped into Expected< ~, Error > if it isn't
761 * of that form already. Consider the following code:
762 *
763 * extern Expected<std::string, Error> readLineFromIO();
764 * extern Expected<int, Error> parseInt(std::string);
765 * extern int increment(int);
766 *
767 * Expected<int, Error> x = readLineFromIO().then(parseInt).then(increment);
768 *
769 * From the code above, we see that .then() works both with functions that
770 * return an Expected< ~, Error > (like parseInt) and with ones that return
771 * a plain value (like increment). In the case of parseInt, .then() returns
772 * the result of parseInt as-is. In the case of increment, it wraps the int
773 * that increment returns into an Expected< int, Error >.
774 *
775 * Sometimes when using a continuation you would prefer an exception to be
776 * thrown for a value-less Expected. For that you can use .thenOrThrow, as
777 * follows:
778 *
779 * B b = someFunc()
780 * .thenOrThrow([](A a){return B(a);});
781 *
782 * The above call to thenOrThrow will invoke the lambda if the Expected returned
783 * by someFunc() contains a value. Otherwise, it will throw an exception of type
784 * Unexpected<Error>::BadExpectedAccess. If you prefer it throw an exception of
785 * a different type, you can pass a second lambda to thenOrThrow:
786 *
787 * B b = someFunc()
788 * .thenOrThrow([](A a){return B(a);},
789 * [](Error e) {throw MyException(e);});
790 *
791 * Like C++17's std::variant, Expected offers the almost-never-empty guarantee;
792 * that is, an Expected<Value, Error> almost always contains either a Value or
793 * and Error. Partially-formed Expected objects occur when an assignment to
794 * an Expected object that would change the type of the contained object (Value-
795 * to-Error or vice versa) throws. Trying to access either the contained value
796 * or error object causes Expected to throw folly::BadExpectedAccess.
797 *
798 * Expected models OptionalPointee, so calling 'get_pointer(ex)' will return a
799 * pointer to nullptr if the 'ex' is in the error state, and a pointer to the
800 * value otherwise:
801 *
802 * Expected<int, Error> maybeInt = ...;
803 * if (int* v = get_pointer(maybeInt)) {
804 * cout << *v << endl;
805 * }
806 */
807 template <class Value, class Error>
808 class Expected final : expected_detail::ExpectedStorage<Value, Error> {
809 template <class, class>
810 friend class Expected;
811 template <class, class, expected_detail::StorageType>
812 friend struct expected_detail::ExpectedStorage;
813 friend struct expected_detail::ExpectedHelper;
814 using Base = expected_detail::ExpectedStorage<Value, Error>;
815 using MakeBadExpectedAccess =
816 typename Unexpected<Error>::MakeBadExpectedAccess;
817 Base& base() & { return *this; }
818 const Base& base() const& { return *this; }
819 Base&& base() && { return std::move(*this); }
820
821 public:
822 using value_type = Value;
823 using error_type = Error;
824
825 template <class U>
826 using rebind = Expected<U, Error>;
827
828 using promise_type = expected_detail::Promise<Value, Error>;
829
830 static_assert(
831 !std::is_reference<Value>::value,
832 "Expected may not be used with reference types");
833 static_assert(
834 !std::is_abstract<Value>::value,
835 "Expected may not be used with abstract types");
836
837 /*
838 * Constructors
839 */
840 template <class B = Base, class = decltype(B{})>
841 Expected() noexcept(noexcept(B{})) : Base{} {}
842 Expected(const Expected& that) = default;
843 Expected(Expected&& that) = default;
844
845 template <
846 class V,
847 class E FOLLY_REQUIRES_TRAILING(
848 !std::is_same<Expected<V, E>, Expected>::value &&
849 std::is_constructible<Value, V&&>::value &&
850 std::is_constructible<Error, E&&>::value)>
851 Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} {
852 this->assign(std::move(that));
853 }
854
855 FOLLY_REQUIRES(std::is_copy_constructible<Value>::value)
856 constexpr /* implicit */ Expected(const Value& val) noexcept(
857 noexcept(Value(val)))
858 : Base{expected_detail::ValueTag{}, val} {}
859
860 FOLLY_REQUIRES(std::is_move_constructible<Value>::value)
861 constexpr /* implicit */ Expected(Value&& val) noexcept(
862 noexcept(Value(std::move(val))))
863 : Base{expected_detail::ValueTag{}, std::move(val)} {}
864
865 template <class T FOLLY_REQUIRES_TRAILING(
866 std::is_convertible<T, Value>::value &&
867 !std::is_convertible<T, Error>::value)>
868 constexpr /* implicit */ Expected(T&& val) noexcept(
869 noexcept(Value(static_cast<T&&>(val))))
870 : Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {}
871
872 template <class... Ts FOLLY_REQUIRES_TRAILING(
873 std::is_constructible<Value, Ts&&...>::value)>
874 explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
875 noexcept(Value(std::declval<Ts>()...)))
876 : Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {}
877
878 template <
879 class U,
880 class... Ts FOLLY_REQUIRES_TRAILING(
881 std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
882 value)>
883 explicit constexpr Expected(
884 in_place_t,
885 std::initializer_list<U> il,
886 Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
887 : Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {}
888
889 // If overload resolution selects one of these deleted functions, that
890 // means you need to use makeUnexpected
891 /* implicit */ Expected(const Error&) = delete;
892 /* implicit */ Expected(Error&&) = delete;
893
894 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
895 constexpr Expected(unexpected_t, const Error& err) noexcept(
896 noexcept(Error(err)))
897 : Base{expected_detail::ErrorTag{}, err} {}
898
899 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
900 constexpr Expected(unexpected_t, Error&& err) noexcept(
901 noexcept(Error(std::move(err))))
902 : Base{expected_detail::ErrorTag{}, std::move(err)} {}
903
904 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
905 constexpr /* implicit */ Expected(const Unexpected<Error>& err) noexcept(
906 noexcept(Error(err.error())))
907 : Base{expected_detail::ErrorTag{}, err.error()} {}
908
909 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
910 constexpr /* implicit */ Expected(Unexpected<Error>&& err) noexcept(
911 noexcept(Error(std::move(err.error()))))
912 : Base{expected_detail::ErrorTag{}, std::move(err.error())} {}
913
914 /*
915 * Assignment operators
916 */
917 Expected& operator=(const Expected& that) = default;
918 Expected& operator=(Expected&& that) = default;
919
920 template <
921 class V,
922 class E FOLLY_REQUIRES_TRAILING(
923 !std::is_same<Expected<V, E>, Expected>::value &&
924 expected_detail::IsConvertible<V&&, Value>::value &&
925 expected_detail::IsConvertible<E&&, Error>::value)>
926 Expected& operator=(Expected<V, E> that) {
927 this->assign(std::move(that));
928 return *this;
929 }
930
931 FOLLY_REQUIRES(expected_detail::IsCopyable<Value>::value)
932 Expected& operator=(const Value& val) noexcept(
933 expected_detail::IsNothrowCopyable<Value>::value) {
934 this->assignValue(val);
935 return *this;
936 }
937
938 FOLLY_REQUIRES(expected_detail::IsMovable<Value>::value)
939 Expected& operator=(Value&& val) noexcept(
940 expected_detail::IsNothrowMovable<Value>::value) {
941 this->assignValue(std::move(val));
942 return *this;
943 }
944
945 template <class T FOLLY_REQUIRES_TRAILING(
946 std::is_convertible<T, Value>::value &&
947 !std::is_convertible<T, Error>::value)>
948 Expected& operator=(T&& val) {
949 this->assignValue(static_cast<T&&>(val));
950 return *this;
951 }
952
953 FOLLY_REQUIRES(expected_detail::IsCopyable<Error>::value)
954 Expected& operator=(const Unexpected<Error>& err) noexcept(
955 expected_detail::IsNothrowCopyable<Error>::value) {
956 this->assignError(err.error());
957 return *this;
958 }
959
960 FOLLY_REQUIRES(expected_detail::IsMovable<Error>::value)
961 Expected& operator=(Unexpected<Error>&& err) noexcept(
962 expected_detail::IsNothrowMovable<Error>::value) {
963 this->assignError(std::move(err.error()));
964 return *this;
965 }
966
967 // Used only when an Expected is used with coroutines on MSVC
968 /* implicit */ Expected(const expected_detail::PromiseReturn<Value, Error>& p)
969 : Expected{} {
970 p.promise_->value_ = this;
971 }
972
973 template <class... Ts FOLLY_REQUIRES_TRAILING(
974 std::is_constructible<Value, Ts&&...>::value)>
975 void emplace(Ts&&... ts) {
976 this->assignValue(static_cast<Ts&&>(ts)...);
977 }
978
979 /**
980 * swap
981 */
982 void swap(Expected& that) noexcept(
983 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
984 if (this->uninitializedByException() || that.uninitializedByException()) {
985 throw_exception<BadExpectedAccess>();
986 }
987 using std::swap;
988 if (*this) {
989 if (that) {
990 swap(this->value_, that.value_);
991 } else {
992 Error e(std::move(that.error_));
993 that.assignValue(std::move(this->value_));
994 this->assignError(std::move(e));
995 }
996 } else {
997 if (!that) {
998 swap(this->error_, that.error_);
999 } else {
1000 Error e(std::move(this->error_));
1001 this->assignValue(std::move(that.value_));
1002 that.assignError(std::move(e));
1003 }
1004 }
1005 }
1006
1007 // If overload resolution selects one of these deleted functions, that
1008 // means you need to use makeUnexpected
1009 /* implicit */ Expected& operator=(const Error&) = delete;
1010 /* implicit */ Expected& operator=(Error&&) = delete;
1011
1012 /**
1013 * Relational Operators
1014 */
1015 template <class Val, class Err>
1016 friend typename std::enable_if<IsEqualityComparable<Val>::value, bool>::type
1017 operator==(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1018 template <class Val, class Err>
1019 friend typename std::enable_if<IsLessThanComparable<Val>::value, bool>::type
1020 operator<(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1021
1022 /*
1023 * Accessors
1024 */
1025 constexpr bool hasValue() const noexcept {
1026 return LIKELY(expected_detail::Which::eValue == this->which_);
1027 }
1028
1029 constexpr bool hasError() const noexcept {
1030 return UNLIKELY(expected_detail::Which::eError == this->which_);
1031 }
1032
1033 using Base::uninitializedByException;
1034
1035 const Value& value() const& {
1036 requireValue();
1037 return this->Base::value();
1038 }
1039
1040 Value& value() & {
1041 requireValue();
1042 return this->Base::value();
1043 }
1044
1045 Value&& value() && {
1046 requireValue();
1047 return std::move(this->Base::value());
1048 }
1049
1050 const Error& error() const& {
1051 requireError();
1052 return this->Base::error();
1053 }
1054
1055 Error& error() & {
1056 requireError();
1057 return this->Base::error();
1058 }
1059
1060 Error&& error() && {
1061 requireError();
1062 return std::move(this->Base::error());
1063 }
1064
1065 // Return a copy of the value if set, or a given default if not.
1066 template <class U>
1067 Value value_or(U&& dflt) const& {
1068 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1069 return this->value_;
1070 }
1071 return static_cast<U&&>(dflt);
1072 }
1073
1074 template <class U>
1075 Value value_or(U&& dflt) && {
1076 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1077 return std::move(this->value_);
1078 }
1079 return static_cast<U&&>(dflt);
1080 }
1081
1082 explicit constexpr operator bool() const noexcept { return hasValue(); }
1083
1084 const Value& operator*() const& { return this->value(); }
1085
1086 Value& operator*() & { return this->value(); }
1087
1088 Value&& operator*() && { return std::move(this->value()); }
1089
1090 const Value* operator->() const { return std::addressof(this->value()); }
1091
1092 Value* operator->() { return std::addressof(this->value()); }
1093
1094 const Value* get_pointer() const& noexcept {
1095 return hasValue() ? std::addressof(this->value_) : nullptr;
1096 }
1097
1098 Value* get_pointer() & noexcept {
1099 return hasValue() ? std::addressof(this->value_) : nullptr;
1100 }
1101
1102 Value* get_pointer() && = delete;
1103
1104 /**
1105 * then
1106 */
1107 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1108 auto then(Fns&&... fns)
1109 const& -> decltype(expected_detail::ExpectedHelper::then_(
1110 std::declval<const Base&>(), std::declval<Fns>()...)) {
1111 if (this->uninitializedByException()) {
1112 throw_exception<BadExpectedAccess>();
1113 }
1114 return expected_detail::ExpectedHelper::then_(
1115 base(), static_cast<Fns&&>(fns)...);
1116 }
1117
1118 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1119 auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1120 std::declval<Base&>(), std::declval<Fns>()...)) {
1121 if (this->uninitializedByException()) {
1122 throw_exception<BadExpectedAccess>();
1123 }
1124 return expected_detail::ExpectedHelper::then_(
1125 base(), static_cast<Fns&&>(fns)...);
1126 }
1127
1128 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1129 auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1130 std::declval<Base&&>(), std::declval<Fns>()...)) {
1131 if (this->uninitializedByException()) {
1132 throw_exception<BadExpectedAccess>();
1133 }
1134 return expected_detail::ExpectedHelper::then_(
1135 std::move(base()), static_cast<Fns&&>(fns)...);
1136 }
1137
1138 /**
1139 * thenOrThrow
1140 */
1141 template <class Yes, class No = MakeBadExpectedAccess>
1142 auto thenOrThrow(Yes&& yes, No&& no = No{})
1143 const& -> decltype(std::declval<Yes>()(std::declval<const Value&>())) {
1144 using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1145 if (this->uninitializedByException()) {
1146 throw_exception<BadExpectedAccess>();
1147 }
1148 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1149 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1150 }
1151
1152 template <class Yes, class No = MakeBadExpectedAccess>
1153 auto thenOrThrow(Yes&& yes, No&& no = No{}) & -> decltype(std::declval<Yes>()(
1154 std::declval<Value&>())) {
1155 using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1156 if (this->uninitializedByException()) {
1157 throw_exception<BadExpectedAccess>();
1158 }
1159 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1160 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1161 }
1162
1163 template <class Yes, class No = MakeBadExpectedAccess>
1164 auto thenOrThrow(
1165 Yes&& yes,
1166 No&& no =
1167 No{}) && -> decltype(std::declval<Yes>()(std::declval<Value&&>())) {
1168 using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1169 if (this->uninitializedByException()) {
1170 throw_exception<BadExpectedAccess>();
1171 }
1172 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1173 std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1174 }
1175
1176 private:
1177 void requireValue() const {
1178 if (UNLIKELY(!hasValue())) {
1179 if (LIKELY(hasError())) {
1180 using Err = typename Unexpected<Error>::BadExpectedAccess;
1181 throw_exception<Err>(this->error_);
1182 }
1183 throw_exception<BadExpectedAccess>();
1184 }
1185 }
1186
1187 void requireError() const {
1188 if (UNLIKELY(!hasError())) {
1189 throw_exception<BadExpectedAccess>();
1190 }
1191 }
1192
1193 expected_detail::Which which() const noexcept { return this->which_; }
1194 };
1195
1196 template <class Value, class Error>
1197 inline typename std::enable_if<IsEqualityComparable<Value>::value, bool>::type
1198 operator==(
1199 const Expected<Value, Error>& lhs, const Expected<Value, Error>& rhs) {
1200 if (UNLIKELY(lhs.uninitializedByException())) {
1201 throw_exception<BadExpectedAccess>();
1202 }
1203 if (UNLIKELY(lhs.which_ != rhs.which_)) {
1204 return false;
1205 }
1206 if (UNLIKELY(lhs.hasError())) {
1207 return true; // All error states are considered equal
1208 }
1209 return lhs.value_ == rhs.value_;
1210 }
1211
1212 template <
1213 class Value,
1214 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Value>::value)>
1215 inline bool operator!=(
1216 const Expected<Value, Error>& lhs, const Expected<Value, Error>& rhs) {
1217 return !(rhs == lhs);
1218 }
1219
1220 template <class Value, class Error>
1221 inline typename std::enable_if<IsLessThanComparable<Value>::value, bool>::type
1222 operator<(
1223 const Expected<Value, Error>& lhs, const Expected<Value, Error>& rhs) {
1224 if (UNLIKELY(
1225 lhs.uninitializedByException() || rhs.uninitializedByException())) {
1226 throw_exception<BadExpectedAccess>();
1227 }
1228 if (UNLIKELY(lhs.hasError())) {
1229 return !rhs.hasError();
1230 }
1231 if (UNLIKELY(rhs.hasError())) {
1232 return false;
1233 }
1234 return lhs.value_ < rhs.value_;
1235 }
1236
1237 template <
1238 class Value,
1239 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1240 inline bool operator<=(
1241 const Expected<Value, Error>& lhs, const Expected<Value, Error>& rhs) {
1242 return !(rhs < lhs);
1243 }
1244
1245 template <
1246 class Value,
1247 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1248 inline bool operator>(
1249 const Expected<Value, Error>& lhs, const Expected<Value, Error>& rhs) {
1250 return rhs < lhs;
1251 }
1252
1253 template <
1254 class Value,
1255 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1256 inline bool operator>=(
1257 const Expected<Value, Error>& lhs, const Expected<Value, Error>& rhs) {
1258 return !(lhs < rhs);
1259 }
1260
1261 /**
1262 * swap Expected values
1263 */
1264 template <class Value, class Error>
1265 void swap(Expected<Value, Error>& lhs, Expected<Value, Error>& rhs) noexcept(
1266 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1267 lhs.swap(rhs);
1268 }
1269
1270 template <class Value, class Error>
1271 const Value* get_pointer(const Expected<Value, Error>& ex) noexcept {
1272 return ex.get_pointer();
1273 }
1274
1275 template <class Value, class Error>
1276 Value* get_pointer(Expected<Value, Error>& ex) noexcept {
1277 return ex.get_pointer();
1278 }
1279
1280 /**
1281 * For constructing an Expected object from a value, with the specified
1282 * Error type. Usage is as follows:
1283 *
1284 * enum MyErrorCode { BAD_ERROR, WORSE_ERROR };
1285 * Expected<int, MyErrorCode> myAPI() {
1286 * int i = // ...;
1287 * return i ? makeExpected<MyErrorCode>(i) : makeUnexpected(BAD_ERROR);
1288 * }
1289 */
1290 template <class Error, class Value>
1291 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
1292 Value&& val) {
1293 return Expected<typename std::decay<Value>::type, Error>{
1294 in_place, static_cast<Value&&>(val)};
1295 }
1296
1297 // Suppress comparability of Optional<T> with T, despite implicit conversion.
1298 template <class Value, class Error>
1299 bool operator==(const Expected<Value, Error>&, const Value& other) = delete;
1300 template <class Value, class Error>
1301 bool operator!=(const Expected<Value, Error>&, const Value& other) = delete;
1302 template <class Value, class Error>
1303 bool operator<(const Expected<Value, Error>&, const Value& other) = delete;
1304 template <class Value, class Error>
1305 bool operator<=(const Expected<Value, Error>&, const Value& other) = delete;
1306 template <class Value, class Error>
1307 bool operator>=(const Expected<Value, Error>&, const Value& other) = delete;
1308 template <class Value, class Error>
1309 bool operator>(const Expected<Value, Error>&, const Value& other) = delete;
1310 template <class Value, class Error>
1311 bool operator==(const Value& other, const Expected<Value, Error>&) = delete;
1312 template <class Value, class Error>
1313 bool operator!=(const Value& other, const Expected<Value, Error>&) = delete;
1314 template <class Value, class Error>
1315 bool operator<(const Value& other, const Expected<Value, Error>&) = delete;
1316 template <class Value, class Error>
1317 bool operator<=(const Value& other, const Expected<Value, Error>&) = delete;
1318 template <class Value, class Error>
1319 bool operator>=(const Value& other, const Expected<Value, Error>&) = delete;
1320 template <class Value, class Error>
1321 bool operator>(const Value& other, const Expected<Value, Error>&) = delete;
1322
1323 } // namespace folly
1324
1325 #undef FOLLY_REQUIRES
1326 #undef FOLLY_REQUIRES_TRAILING
1327
1328 // Enable the use of folly::Expected with `co_await`
1329 // Inspired by https://github.com/toby-allsopp/coroutine_monad
1330 #if FOLLY_HAS_COROUTINES
1331 #include <folly/experimental/coro/Coroutine.h>
1332
1333 namespace folly {
1334 namespace expected_detail {
1335 template <typename Value, typename Error>
1336 struct Promise;
1337
1338 template <typename Value, typename Error>
1339 struct PromiseReturn {
1340 Optional<Expected<Value, Error>> storage_;
1341 Promise<Value, Error>* promise_;
1342 /* implicit */ PromiseReturn(Promise<Value, Error>& promise) noexcept
1343 : promise_(&promise) {
1344 promise_->value_ = &storage_;
1345 }
1346 PromiseReturn(PromiseReturn&& that) noexcept
1347 : PromiseReturn{*that.promise_} {}
1348 ~PromiseReturn() {}
1349 /* implicit */ operator Expected<Value, Error>() & {
1350 return std::move(*storage_);
1351 }
1352 };
1353
1354 template <typename Value, typename Error>
1355 struct Promise {
1356 Optional<Expected<Value, Error>>* value_ = nullptr;
1357 Promise() = default;
1358 Promise(Promise const&) = delete;
1359 // This should work regardless of whether the compiler generates:
1360 // folly::Expected<Value, Error> retobj{ p.get_return_object(); } // MSVC
1361 // or:
1362 // auto retobj = p.get_return_object(); // clang
1363 PromiseReturn<Value, Error> get_return_object() noexcept { return *this; }
1364 coro::suspend_never initial_suspend() const noexcept { return {}; }
1365 coro::suspend_never final_suspend() const noexcept { return {}; }
1366 template <typename U = Value>
1367 void return_value(U&& u) {
1368 value_->emplace(static_cast<U&&>(u));
1369 }
1370 void unhandled_exception() {
1371 // Technically, throwing from unhandled_exception is underspecified:
1372 // https://github.com/GorNishanov/CoroutineWording/issues/17
1373 rethrow_current_exception();
1374 }
1375 };
1376
1377 template <typename Value, typename Error>
1378 struct Awaitable {
1379 Expected<Value, Error> o_;
1380
1381 explicit Awaitable(Expected<Value, Error> o) : o_(std::move(o)) {}
1382
1383 bool await_ready() const noexcept { return o_.hasValue(); }
1384 Value await_resume() { return std::move(o_.value()); }
1385
1386 // Explicitly only allow suspension into a Promise
1387 template <typename U>
1388 void await_suspend(coro::coroutine_handle<Promise<U, Error>> h) {
1389 *h.promise().value_ = makeUnexpected(std::move(o_.error()));
1390 // Abort the rest of the coroutine. resume() is not going to be called
1391 h.destroy();
1392 }
1393 };
1394 } // namespace expected_detail
1395
1396 template <typename Value, typename Error>
1397 expected_detail::Awaitable<Value, Error>
1398 /* implicit */ operator co_await(Expected<Value, Error> o) {
1399 return expected_detail::Awaitable<Value, Error>{std::move(o)};
1400 }
1401 } // namespace folly
1402 #endif // FOLLY_HAS_COROUTINES
1403