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