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