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