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