proxygen
Expected.h
Go to the documentation of this file.
1 /*
2  * Copyright 2016-present 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  */
22 #pragma once
23 
24 #include <cstddef>
25 #include <initializer_list>
26 #include <new>
27 #include <stdexcept>
28 #include <type_traits>
29 #include <utility>
30 
31 #include <folly/CPortability.h>
32 #include <folly/CppAttributes.h>
33 #include <folly/Likely.h>
34 #include <folly/Optional.h>
35 #include <folly/Portability.h>
36 #include <folly/Preprocessor.h>
37 #include <folly/Traits.h>
38 #include <folly/Unit.h>
39 #include <folly/Utility.h>
40 #include <folly/lang/ColdClass.h>
41 #include <folly/lang/Exception.h>
42 
43 #define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__)
44 
45 #define FOLLY_REQUIRES_IMPL(...) \
46  bool FOLLY_EXPECTED_ID(Requires) = false, \
47  typename std::enable_if< \
48  (FOLLY_EXPECTED_ID(Requires) || static_cast<bool>(__VA_ARGS__)), \
49  int>::type = 0
50 
51 #define FOLLY_REQUIRES_TRAILING(...) , FOLLY_REQUIRES_IMPL(__VA_ARGS__)
52 
53 #define FOLLY_REQUIRES(...) template <FOLLY_REQUIRES_IMPL(__VA_ARGS__)>
54 
59 #if defined(__GNUC__) && !defined(__clang__)
60 #pragma GCC diagnostic push
61 #pragma GCC diagnostic ignored "-Wuninitialized"
62 #pragma GCC diagnostic ignored "-Wpragmas"
63 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
64 #endif // __GNUC__
65 
66 namespace folly {
67 
71 template <class Error>
72 class Unexpected;
73 
74 template <class Error>
76 
77 template <class Value, class Error>
78 class Expected;
79 
80 template <class Error, class Value>
82  Value&&);
83 
87 template <class Expected>
88 using ExpectedValueType =
89  typename std::remove_reference<Expected>::type::value_type;
90 
94 template <class Expected>
95 using ExpectedErrorType =
96  typename std::remove_reference<Expected>::type::error_type;
97 
98 // Details...
99 namespace expected_detail {
100 
101 template <typename Value, typename Error>
103 
104 #ifdef _MSC_VER
105 // MSVC 2015 can't handle the StrictConjunction, so we have
106 // to use std::conjunction instead.
107 template <template <class...> class Trait, class... Ts>
108 using StrictAllOf = std::conjunction<Trait<Ts>...>;
109 #else
110 template <template <class...> class Trait, class... Ts>
111 using StrictAllOf = StrictConjunction<Trait<Ts>...>;
112 #endif
113 
114 template <class T>
116  std::is_copy_constructible<T>,
117  std::is_copy_assignable<T>>;
118 
119 template <class T>
121  std::is_move_constructible<T>,
122  std::is_move_assignable<T>>;
123 
124 template <class T>
126  std::is_nothrow_copy_constructible<T>,
127  std::is_nothrow_copy_assignable<T>>;
128 
129 template <class T>
131  std::is_nothrow_move_constructible<T>,
132  std::is_nothrow_move_assignable<T>>;
133 
134 template <class From, class To>
136  std::is_constructible<To, From>,
137  std::is_assignable<To&, From>>;
138 
139 template <class T, class U>
140 auto doEmplaceAssign(int, T& t, U&& u)
141  -> decltype(void(t = static_cast<U&&>(u))) {
142  t = static_cast<U&&>(u);
143 }
144 
145 template <class T, class U>
146 auto doEmplaceAssign(long, T& t, U&& u)
147  -> decltype(void(T(static_cast<U&&>(u)))) {
148  t.~T();
149  ::new ((void*)std::addressof(t)) T(static_cast<U&&>(u));
150 }
151 
152 template <class T, class... Us>
153 auto doEmplaceAssign(int, T& t, Us&&... us)
154  -> decltype(void(t = T(static_cast<Us&&>(us)...))) {
155  t = T(static_cast<Us&&>(us)...);
156 }
157 
158 template <class T, class... Us>
159 auto doEmplaceAssign(long, T& t, Us&&... us)
160  -> decltype(void(T(static_cast<Us&&>(us)...))) {
161  t.~T();
162  ::new ((void*)std::addressof(t)) T(static_cast<Us&&>(us)...);
163 }
164 
165 struct EmptyTag {};
166 struct ValueTag {};
167 struct ErrorTag {};
168 enum class Which : unsigned char { eEmpty, eValue, eError };
170 
171 template <class Value, class Error>
174  ? (sizeof(std::pair<Value, Error>) <= sizeof(void * [2]) &&
179 }
180 
181 template <
182  class Value,
183  class Error,
184  StorageType = expected_detail::getStorageType<Value, Error>()> // ePODUnion
186  using value_type = Value;
187  using error_type = Error;
188  union {
189  Value value_;
190  Error error_;
191  char ch_;
192  };
194 
195  template <class E = Error, class = decltype(E{})>
197  : error_{}, which_(Which::eError) {}
198  explicit constexpr ExpectedStorage(EmptyTag) noexcept
199  : ch_{}, which_(Which::eEmpty) {}
200  template <class... Vs>
201  explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
202  noexcept(Value(static_cast<Vs&&>(vs)...)))
203  : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
204  template <class... Es>
205  explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
206  noexcept(Error(static_cast<Es&&>(es)...)))
207  : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
208  void clear() noexcept {}
209  static constexpr bool uninitializedByException() noexcept {
210  // Although which_ may temporarily be eEmpty during construction, it
211  // is always either eValue or eError for a fully-constructed Expected.
212  return false;
213  }
214  template <class... Vs>
215  void assignValue(Vs&&... vs) {
216  expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
217  which_ = Which::eValue;
218  }
219  template <class... Es>
220  void assignError(Es&&... es) {
221  expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
222  which_ = Which::eError;
223  }
224  template <class Other>
225  void assign(Other&& that) {
226  switch (that.which_) {
227  case Which::eValue:
228  this->assignValue(static_cast<Other&&>(that).value());
229  break;
230  case Which::eError:
231  this->assignError(static_cast<Other&&>(that).error());
232  break;
233  default:
234  this->clear();
235  break;
236  }
237  }
238  Value& value() & {
239  return value_;
240  }
241  const Value& value() const& {
242  return value_;
243  }
244  Value&& value() && {
245  return std::move(value_);
246  }
247  // TODO (t17322426): remove when VS2015 support is deprecated
248  // VS2015 static analyzer incorrectly flags these as unreachable in certain
249  // circumstances. VS2017 does not have this problem on the same code.
251  FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
252  Error& error() & {
253  return error_;
254  }
255  const Error& error() const& {
256  return error_;
257  }
258  Error&& error() && {
259  return std::move(error_);
260  }
262 };
263 
264 template <class Value, class Error>
266  union {
267  Value value_;
268  Error error_;
269  char ch_{};
270  };
272 
273  explicit constexpr ExpectedUnion(EmptyTag) noexcept {}
274  template <class... Vs>
275  explicit constexpr ExpectedUnion(ValueTag, Vs&&... vs) noexcept(
276  noexcept(Value(static_cast<Vs&&>(vs)...)))
277  : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
278  template <class... Es>
279  explicit constexpr ExpectedUnion(ErrorTag, Es&&... es) noexcept(
280  noexcept(Error(static_cast<Es&&>(es)...)))
281  : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
285  return *this;
286  }
288  return *this;
289  }
291  Value& value() & {
292  return value_;
293  }
294  const Value& value() const& {
295  return value_;
296  }
297  Value&& value() && {
298  return std::move(value_);
299  }
300  Error& error() & {
301  return error_;
302  }
303  const Error& error() const& {
304  return error_;
305  }
306  Error&& error() && {
307  return std::move(error_);
308  }
309 };
310 
311 template <class Derived, bool, bool Noexcept>
313  constexpr CopyConstructible() = default;
315  static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
316  }
317  constexpr CopyConstructible(CopyConstructible&&) = default;
318  CopyConstructible& operator=(const CopyConstructible&) = default;
319  CopyConstructible& operator=(CopyConstructible&&) = default;
320 };
321 
322 template <class Derived, bool Noexcept>
323 struct CopyConstructible<Derived, false, Noexcept> {
324  constexpr CopyConstructible() = default;
325  CopyConstructible(const CopyConstructible&) = delete;
326  constexpr CopyConstructible(CopyConstructible&&) = default;
327  CopyConstructible& operator=(const CopyConstructible&) = default;
328  CopyConstructible& operator=(CopyConstructible&&) = default;
329 };
330 
331 template <class Derived, bool, bool Noexcept>
333  constexpr MoveConstructible() = default;
334  constexpr MoveConstructible(const MoveConstructible&) = default;
336  static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
337  }
338  MoveConstructible& operator=(const MoveConstructible&) = default;
339  MoveConstructible& operator=(MoveConstructible&&) = default;
340 };
341 
342 template <class Derived, bool Noexcept>
343 struct MoveConstructible<Derived, false, Noexcept> {
344  constexpr MoveConstructible() = default;
345  constexpr MoveConstructible(const MoveConstructible&) = default;
347  MoveConstructible& operator=(const MoveConstructible&) = default;
348  MoveConstructible& operator=(MoveConstructible&&) = default;
349 };
350 
351 template <class Derived, bool, bool Noexcept>
353  constexpr CopyAssignable() = default;
354  constexpr CopyAssignable(const CopyAssignable&) = default;
355  constexpr CopyAssignable(CopyAssignable&&) = default;
357  static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
358  return *this;
359  }
360  CopyAssignable& operator=(CopyAssignable&&) = default;
361 };
362 
363 template <class Derived, bool Noexcept>
364 struct CopyAssignable<Derived, false, Noexcept> {
365  constexpr CopyAssignable() = default;
366  constexpr CopyAssignable(const CopyAssignable&) = default;
367  constexpr CopyAssignable(CopyAssignable&&) = default;
368  CopyAssignable& operator=(const CopyAssignable&) = delete;
369  CopyAssignable& operator=(CopyAssignable&&) = default;
370 };
371 
372 template <class Derived, bool, bool Noexcept>
374  constexpr MoveAssignable() = default;
375  constexpr MoveAssignable(const MoveAssignable&) = default;
376  constexpr MoveAssignable(MoveAssignable&&) = default;
377  MoveAssignable& operator=(const MoveAssignable&) = default;
379  static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
380  return *this;
381  }
382 };
383 
384 template <class Derived, bool Noexcept>
385 struct MoveAssignable<Derived, false, Noexcept> {
386  constexpr MoveAssignable() = default;
387  constexpr MoveAssignable(const MoveAssignable&) = default;
388  constexpr MoveAssignable(MoveAssignable&&) = default;
389  MoveAssignable& operator=(const MoveAssignable&) = default;
390  MoveAssignable& operator=(MoveAssignable&& that) = delete;
391 };
392 
393 template <class Value, class Error>
394 struct ExpectedStorage<Value, Error, StorageType::eUnion>
395  : ExpectedUnion<Value, Error>,
397  ExpectedStorage<Value, Error, StorageType::eUnion>,
398  StrictAllOf<std::is_copy_constructible, Value, Error>::value,
399  StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::value>,
401  ExpectedStorage<Value, Error, StorageType::eUnion>,
402  StrictAllOf<std::is_move_constructible, Value, Error>::value,
403  StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::value>,
405  ExpectedStorage<Value, Error, StorageType::eUnion>,
406  StrictAllOf<IsCopyable, Value, Error>::value,
407  StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
409  ExpectedStorage<Value, Error, StorageType::eUnion>,
410  StrictAllOf<IsMovable, Value, Error>::value,
411  StrictAllOf<IsNothrowMovable, Value, Error>::value> {
412  using value_type = Value;
413  using error_type = Error;
415  template <class E = Error, class = decltype(E{})>
416  constexpr ExpectedStorage() noexcept(noexcept(E{})) : Base{ErrorTag{}} {}
417  ExpectedStorage(const ExpectedStorage&) = default;
418  ExpectedStorage(ExpectedStorage&&) = default;
419  ExpectedStorage& operator=(const ExpectedStorage&) = default;
420  ExpectedStorage& operator=(ExpectedStorage&&) = default;
423  clear();
424  }
425  void clear() noexcept {
426  switch (this->which_) {
427  case Which::eValue:
428  this->value().~Value();
429  break;
430  case Which::eError:
431  this->error().~Error();
432  break;
433  default:
434  break;
435  }
436  this->which_ = Which::eEmpty;
437  }
439  return this->which_ == Which::eEmpty;
440  }
441  template <class... Vs>
442  void assignValue(Vs&&... vs) {
443  if (this->which_ == Which::eValue) {
445  0, this->value(), static_cast<Vs&&>(vs)...);
446  } else {
447  this->clear();
448  ::new ((void*)std::addressof(this->value()))
449  Value(static_cast<Vs&&>(vs)...);
450  this->which_ = Which::eValue;
451  }
452  }
453  template <class... Es>
454  void assignError(Es&&... es) {
455  if (this->which_ == Which::eError) {
457  0, this->error(), static_cast<Es&&>(es)...);
458  } else {
459  this->clear();
460  ::new ((void*)std::addressof(this->error()))
461  Error(static_cast<Es&&>(es)...);
462  this->which_ = Which::eError;
463  }
464  }
465  bool isSelfAssign(const ExpectedStorage* that) const {
466  return this == that;
467  }
468  constexpr bool isSelfAssign(const void*) const {
469  return false;
470  }
471  template <class Other>
472  void assign(Other&& that) {
473  if (isSelfAssign(&that)) {
474  return;
475  }
476  switch (that.which_) {
477  case Which::eValue:
478  this->assignValue(static_cast<Other&&>(that).value());
479  break;
480  case Which::eError:
481  this->assignError(static_cast<Other&&>(that).error());
482  break;
483  default:
484  this->clear();
485  break;
486  }
487  }
488 };
489 
490 // For small (pointer-sized) trivial types, a struct is faster than a union.
491 template <class Value, class Error>
492 struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
493  using value_type = Value;
494  using error_type = Error;
496  Error error_;
497  Value value_;
498 
500  : which_(Which::eError), error_{}, value_{} {}
501  explicit constexpr ExpectedStorage(EmptyTag) noexcept
502  : which_(Which::eEmpty), error_{}, value_{} {}
503  template <class... Vs>
504  explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
505  noexcept(Value(static_cast<Vs&&>(vs)...)))
506  : which_(Which::eValue), error_{}, value_(static_cast<Vs&&>(vs)...) {}
507  template <class... Es>
508  explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
509  noexcept(Error(static_cast<Es&&>(es)...)))
510  : which_(Which::eError), error_(static_cast<Es&&>(es)...), value_{} {}
511  void clear() noexcept {}
512  constexpr static bool uninitializedByException() noexcept {
513  return false;
514  }
515  template <class... Vs>
516  void assignValue(Vs&&... vs) {
517  expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
518  which_ = Which::eValue;
519  }
520  template <class... Es>
521  void assignError(Es&&... es) {
522  expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
523  which_ = Which::eError;
524  }
525  template <class Other>
526  void assign(Other&& that) {
527  switch (that.which_) {
528  case Which::eValue:
529  this->assignValue(static_cast<Other&&>(that).value());
530  break;
531  case Which::eError:
532  this->assignError(static_cast<Other&&>(that).error());
533  break;
534  default:
535  this->clear();
536  break;
537  }
538  }
539  Value& value() & {
540  return value_;
541  }
542  const Value& value() const& {
543  return value_;
544  }
545  Value&& value() && {
546  return std::move(value_);
547  }
548  // TODO (t17322426): remove when VS2015 support is deprecated
549  // VS2015 static analyzer incorrectly flags these as unreachable in certain
550  // circumstances. VS2017 does not have this problem on the same code.
552  FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
553  Error& error() & {
554  return error_;
555  }
556  const Error& error() const& {
557  return error_;
558  }
559  Error&& error() && {
560  return std::move(error_);
561  }
563 };
564 
565 namespace expected_detail_ExpectedHelper {
566 // Tricky hack so that Expected::then can handle lambdas that return void
567 template <class T>
568 inline T&& operator,(T&& t, Unit) noexcept {
569  return static_cast<T&&>(t);
570 }
571 
573  template <class Error, class T>
574  static constexpr Expected<T, Error> return_(T t) {
575  return folly::makeExpected<Error>(t);
576  }
577  template <
578  class Error,
579  class T,
580  class U FOLLY_REQUIRES_TRAILING(
583  return t;
584  }
585 
586  template <class This>
587  static typename std::decay<This>::type then_(This&& ex) {
588  return static_cast<This&&>(ex);
589  }
590 
592  // Don't warn about not using the overloaded comma operator.
594  template <
595  class This,
596  class Fn,
597  class... Fns,
598  class E = ExpectedErrorType<This>,
599  class T = ExpectedHelper>
600  static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
601  T::template return_<E>(
602  (std::declval<Fn>()(std::declval<This>().value()), unit)),
603  std::declval<Fns>()...)) {
604  if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
605  return T::then_(
606  T::template return_<E>(
607  // Uses the comma operator defined above IFF the lambda
608  // returns non-void.
609  (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
610  static_cast<Fns&&>(fns)...);
611  }
612  return makeUnexpected(static_cast<This&&>(ex).error());
613  }
614 
615  template <
616  class This,
617  class Yes,
618  class No,
619  class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
620  class Err = decltype(std::declval<No>()(std::declval<This>().error()))
622  static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
623  if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
624  return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
625  }
626  throw_exception(static_cast<No&&>(no)(static_cast<This&&>(ex).error()));
627  }
628 
629  template <
630  class This,
631  class Yes,
632  class No,
633  class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
634  class Err = decltype(std::declval<No>()(std::declval<This&>().error()))
636  static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
637  if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
638  return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
639  }
640  static_cast<No&&>(no)(ex.error());
641  typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess bad;
642  throw_exception(bad(static_cast<This&&>(ex).error()));
643  }
645 };
646 } // namespace expected_detail_ExpectedHelper
647 /* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
648 
649 struct UnexpectedTag {};
650 
651 } // namespace expected_detail
652 
653 using unexpected_t =
655 
658  return {};
659 }
660 
664 class FOLLY_EXPORT BadExpectedAccess : public std::logic_error {
665  public:
666  BadExpectedAccess() : std::logic_error("bad Expected access") {}
667 };
668 
669 namespace expected_detail {
670 // empty
671 } // namespace expected_detail
672 
677 template <class Error>
678 class Unexpected final : ColdClass {
679  template <class E>
680  friend class Unexpected;
681  template <class V, class E>
682  friend class Expected;
683  friend struct expected_detail::ExpectedHelper;
684 
685  public:
692  public:
693  explicit BadExpectedAccess(Error err)
694  : folly::BadExpectedAccess{}, error_(std::move(err)) {}
699  Error error() const {
700  return error_;
701  }
702 
703  private:
704  Error error_;
705  };
706 
710  Unexpected() = default;
711  Unexpected(const Unexpected&) = default;
712  Unexpected(Unexpected&&) = default;
713  Unexpected& operator=(const Unexpected&) = default;
714  Unexpected& operator=(Unexpected&&) = default;
715  constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {}
716  constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {}
717 
718  template <class Other FOLLY_REQUIRES_TRAILING(
720  constexpr /* implicit */ Unexpected(Unexpected<Other> that)
721  : error_(std::move(that.error())) {}
722 
726  template <class Other FOLLY_REQUIRES_TRAILING(
729  error_ = std::move(that.error());
730  }
731 
735  Error& error() & {
736  return error_;
737  }
738  const Error& error() const& {
739  return error_;
740  }
741  Error&& error() && {
742  return std::move(error_);
743  }
744 
745  private:
747  template <class E>
748  BadExpectedAccess operator()(E&& err) const {
749  return BadExpectedAccess(static_cast<E&&>(err));
750  }
751  };
752 
753  Error error_;
754 };
755 
756 template <
758 inline bool operator==(
759  const Unexpected<Error>& lhs,
760  const Unexpected<Error>& rhs) {
761  return lhs.error() == rhs.error();
762 }
763 
764 template <
766 inline bool operator!=(
767  const Unexpected<Error>& lhs,
768  const Unexpected<Error>& rhs) {
769  return !(lhs == rhs);
770 }
771 
784 template <class Error>
786  Error&& err) {
788  static_cast<Error&&>(err)};
789 }
790 
885 template <class Value, class Error>
886 class Expected final : expected_detail::ExpectedStorage<Value, Error> {
887  template <class, class>
888  friend class Expected;
889  template <class, class, expected_detail::StorageType>
891  friend struct expected_detail::ExpectedHelper;
893  using MakeBadExpectedAccess =
895  Base& base() & {
896  return *this;
897  }
898  const Base& base() const& {
899  return *this;
900  }
901  Base&& base() && {
902  return std::move(*this);
903  }
904 
905  public:
906  using value_type = Value;
907  using error_type = Error;
908 
909  template <class U>
911 
912  static_assert(
914  "Expected may not be used with reference types");
915  static_assert(
917  "Expected may not be used with abstract types");
918 
919  /*
920  * Constructors
921  */
922  template <class B = Base, class = decltype(B{})>
924  Expected(const Expected& that) = default;
925  Expected(Expected&& that) = default;
926 
927  template <
928  class V,
929  class E FOLLY_REQUIRES_TRAILING(
930  !std::is_same<Expected<V, E>, Expected>::value &&
934  *this = std::move(that);
935  }
936 
938  constexpr /* implicit */ Expected(const Value& val) noexcept(
939  noexcept(Value(val)))
941 
943  constexpr /* implicit */ Expected(Value&& val) noexcept(
944  noexcept(Value(std::move(val))))
946 
947  template <class T FOLLY_REQUIRES_TRAILING(
950  constexpr /* implicit */ Expected(T&& val) noexcept(
951  noexcept(Value(static_cast<T&&>(val))))
952  : Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {}
953 
954  template <class... Ts FOLLY_REQUIRES_TRAILING(
956  explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
957  noexcept(Value(std::declval<Ts>()...)))
958  : Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {}
959 
960  template <
961  class U,
962  class... Ts FOLLY_REQUIRES_TRAILING(
963  std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
964  value)>
965  explicit constexpr Expected(
966  in_place_t,
967  std::initializer_list<U> il,
968  Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
969  : Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {}
970 
971  // If overload resolution selects one of these deleted functions, that
972  // means you need to use makeUnexpected
973  /* implicit */ Expected(const Error&) = delete;
974  /* implicit */ Expected(Error&&) = delete;
975 
977  constexpr Expected(unexpected_t, const Error& err) noexcept(
978  noexcept(Error(err)))
979  : Base{expected_detail::ErrorTag{}, err} {}
980 
982  constexpr Expected(unexpected_t, Error&& err) noexcept(
983  noexcept(Error(std::move(err))))
985 
987  constexpr /* implicit */ Expected(const Unexpected<Error>& err) noexcept(
988  noexcept(Error(err.error())))
989  : Base{expected_detail::ErrorTag{}, err.error()} {}
990 
992  constexpr /* implicit */ Expected(Unexpected<Error>&& err) noexcept(
993  noexcept(Error(std::move(err.error()))))
994  : Base{expected_detail::ErrorTag{}, std::move(err.error())} {}
995 
996  /*
997  * Assignment operators
998  */
999  Expected& operator=(const Expected& that) = default;
1000  Expected& operator=(Expected&& that) = default;
1001 
1002  template <
1003  class V,
1004  class E FOLLY_REQUIRES_TRAILING(
1005  !std::is_same<Expected<V, E>, Expected>::value &&
1009  this->assign(std::move(that));
1010  return *this;
1011  }
1012 
1014  Expected& operator=(const Value& val) noexcept(
1015  expected_detail::IsNothrowCopyable<Value>::value) {
1016  this->assignValue(val);
1017  return *this;
1018  }
1019 
1021  Expected& operator=(Value&& val) noexcept(
1022  expected_detail::IsNothrowMovable<Value>::value) {
1023  this->assignValue(std::move(val));
1024  return *this;
1025  }
1026 
1027  template <class T FOLLY_REQUIRES_TRAILING(
1031  this->assignValue(static_cast<T&&>(val));
1032  return *this;
1033  }
1034 
1036  Expected& operator=(const Unexpected<Error>& err) noexcept(
1037  expected_detail::IsNothrowCopyable<Error>::value) {
1038  this->assignError(err.error());
1039  return *this;
1040  }
1041 
1043  Expected& operator=(Unexpected<Error>&& err) noexcept(
1044  expected_detail::IsNothrowMovable<Error>::value) {
1045  this->assignError(std::move(err.error()));
1046  return *this;
1047  }
1048 
1049  // Used only when an Expected is used with coroutines on MSVC
1051  : Expected{} {
1052  p.promise_->value_ = this;
1053  }
1054 
1055  template <class... Ts FOLLY_REQUIRES_TRAILING(
1057  void emplace(Ts&&... ts) {
1058  this->assignValue(static_cast<Ts&&>(ts)...);
1059  }
1060 
1064  void swap(Expected& that) noexcept(
1066  if (this->uninitializedByException() || that.uninitializedByException()) {
1067  throw_exception<BadExpectedAccess>();
1068  }
1069  using std::swap;
1070  if (*this) {
1071  if (that) {
1072  swap(this->value_, that.value_);
1073  } else {
1074  Error e(std::move(that.error_));
1075  that.assignValue(std::move(this->value_));
1076  this->assignError(std::move(e));
1077  }
1078  } else {
1079  if (!that) {
1080  swap(this->error_, that.error_);
1081  } else {
1082  Error e(std::move(this->error_));
1083  this->assignValue(std::move(that.value_));
1084  that.assignError(std::move(e));
1085  }
1086  }
1087  }
1088 
1089  // If overload resolution selects one of these deleted functions, that
1090  // means you need to use makeUnexpected
1091  /* implicit */ Expected& operator=(const Error&) = delete;
1092  /* implicit */ Expected& operator=(Error&&) = delete;
1093 
1097  template <class Val, class Err>
1100  template <class Val, class Err>
1102  operator<(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1103 
1104  /*
1105  * Accessors
1106  */
1107  constexpr bool hasValue() const noexcept {
1108  return LIKELY(expected_detail::Which::eValue == this->which_);
1109  }
1110 
1111  constexpr bool hasError() const noexcept {
1112  return UNLIKELY(expected_detail::Which::eError == this->which_);
1113  }
1114 
1115  using Base::uninitializedByException;
1116 
1117  const Value& value() const& {
1118  requireValue();
1119  return this->Base::value();
1120  }
1121 
1122  Value& value() & {
1123  requireValue();
1124  return this->Base::value();
1125  }
1126 
1127  Value&& value() && {
1128  requireValue();
1129  return std::move(this->Base::value());
1130  }
1131 
1132  const Error& error() const& {
1133  requireError();
1134  return this->Base::error();
1135  }
1136 
1137  Error& error() & {
1138  requireError();
1139  return this->Base::error();
1140  }
1141 
1142  Error&& error() && {
1143  requireError();
1144  return std::move(this->Base::error());
1145  }
1146 
1147  // Return a copy of the value if set, or a given default if not.
1148  template <class U>
1149  Value value_or(U&& dflt) const& {
1150  if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1151  return this->value_;
1152  }
1153  return static_cast<U&&>(dflt);
1154  }
1155 
1156  template <class U>
1157  Value value_or(U&& dflt) && {
1158  if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1159  return std::move(this->value_);
1160  }
1161  return static_cast<U&&>(dflt);
1162  }
1163 
1164  explicit constexpr operator bool() const noexcept {
1165  return hasValue();
1166  }
1167 
1168  const Value& operator*() const& {
1169  return this->value();
1170  }
1171 
1172  Value& operator*() & {
1173  return this->value();
1174  }
1175 
1176  Value&& operator*() && {
1177  return std::move(this->value());
1178  }
1179 
1180  const Value* operator->() const {
1181  return std::addressof(this->value());
1182  }
1183 
1184  Value* operator->() {
1185  return std::addressof(this->value());
1186  }
1187 
1188  const Value* get_pointer() const& noexcept {
1189  return hasValue() ? std::addressof(this->value_) : nullptr;
1190  }
1191 
1192  Value* get_pointer() & noexcept {
1193  return hasValue() ? std::addressof(this->value_) : nullptr;
1194  }
1195 
1196  Value* get_pointer() && = delete;
1197 
1201  template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1202  auto then(Fns&&... fns) const& -> decltype(
1203  expected_detail::ExpectedHelper::then_(
1204  std::declval<const Base&>(),
1205  std::declval<Fns>()...)) {
1206  if (this->uninitializedByException()) {
1207  throw_exception<BadExpectedAccess>();
1208  }
1209  return expected_detail::ExpectedHelper::then_(
1210  base(), static_cast<Fns&&>(fns)...);
1211  }
1212 
1213  template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1214  auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1215  std::declval<Base&>(),
1216  std::declval<Fns>()...)) {
1217  if (this->uninitializedByException()) {
1218  throw_exception<BadExpectedAccess>();
1219  }
1220  return expected_detail::ExpectedHelper::then_(
1221  base(), static_cast<Fns&&>(fns)...);
1222  }
1223 
1224  template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1225  auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1226  std::declval<Base&&>(),
1227  std::declval<Fns>()...)) {
1228  if (this->uninitializedByException()) {
1229  throw_exception<BadExpectedAccess>();
1230  }
1231  return expected_detail::ExpectedHelper::then_(
1232  std::move(base()), static_cast<Fns&&>(fns)...);
1233  }
1234 
1238  template <class Yes, class No = MakeBadExpectedAccess>
1239  auto thenOrThrow(Yes&& yes, No&& no = No{}) const& -> decltype(
1240  std::declval<Yes>()(std::declval<const Value&>())) {
1241  using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1242  if (this->uninitializedByException()) {
1243  throw_exception<BadExpectedAccess>();
1244  }
1245  return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1246  base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1247  }
1248 
1249  template <class Yes, class No = MakeBadExpectedAccess>
1250  auto thenOrThrow(Yes&& yes, No&& no = No{}) & -> decltype(
1251  std::declval<Yes>()(std::declval<Value&>())) {
1252  using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1253  if (this->uninitializedByException()) {
1254  throw_exception<BadExpectedAccess>();
1255  }
1256  return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1257  base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1258  }
1259 
1260  template <class Yes, class No = MakeBadExpectedAccess>
1261  auto thenOrThrow(Yes&& yes, No&& no = No{}) && -> decltype(
1262  std::declval<Yes>()(std::declval<Value&&>())) {
1263  using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1264  if (this->uninitializedByException()) {
1265  throw_exception<BadExpectedAccess>();
1266  }
1267  return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1268  std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1269  }
1270 
1271  private:
1272  void requireValue() const {
1273  if (UNLIKELY(!hasValue())) {
1274  if (LIKELY(hasError())) {
1275  using Err = typename Unexpected<Error>::BadExpectedAccess;
1276  throw_exception<Err>(this->error_);
1277  }
1278  throw_exception<BadExpectedAccess>();
1279  }
1280  }
1281 
1282  void requireError() const {
1283  if (UNLIKELY(!hasError())) {
1284  throw_exception<BadExpectedAccess>();
1285  }
1286  }
1287 
1289  return this->which_;
1290  }
1291 };
1292 
1293 template <class Value, class Error>
1296  const Expected<Value, Error>& lhs,
1297  const Expected<Value, Error>& rhs) {
1298  if (UNLIKELY(lhs.uninitializedByException())) {
1299  throw_exception<BadExpectedAccess>();
1300  }
1301  if (UNLIKELY(lhs.which_ != rhs.which_)) {
1302  return false;
1303  }
1304  if (UNLIKELY(lhs.hasError())) {
1305  return true; // All error states are considered equal
1306  }
1307  return lhs.value_ == rhs.value_;
1308 }
1309 
1310 template <
1311  class 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 <class Value, class Error>
1322  const Expected<Value, Error>& lhs,
1323  const Expected<Value, Error>& rhs) {
1324  if (UNLIKELY(
1326  throw_exception<BadExpectedAccess>();
1327  }
1328  if (UNLIKELY(lhs.hasError())) {
1329  return !rhs.hasError();
1330  }
1331  if (UNLIKELY(rhs.hasError())) {
1332  return false;
1333  }
1334  return lhs.value_ < rhs.value_;
1335 }
1336 
1337 template <
1338  class Value,
1340 inline bool operator<=(
1341  const Expected<Value, Error>& lhs,
1342  const Expected<Value, Error>& rhs) {
1343  return !(rhs < lhs);
1344 }
1345 
1346 template <
1347  class Value,
1349 inline bool operator>(
1350  const Expected<Value, Error>& lhs,
1351  const Expected<Value, Error>& rhs) {
1352  return rhs < lhs;
1353 }
1354 
1355 template <
1356  class Value,
1358 inline bool operator>=(
1359  const Expected<Value, Error>& lhs,
1360  const Expected<Value, Error>& rhs) {
1361  return !(lhs < rhs);
1362 }
1363 
1367 template <class Value, class Error>
1370  lhs.swap(rhs);
1371 }
1372 
1373 template <class Value, class Error>
1375  return ex.get_pointer();
1376 }
1377 
1378 template <class Value, class Error>
1380  return ex.get_pointer();
1381 }
1382 
1393 template <class Error, class Value>
1394 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
1395  Value&& val) {
1396  return Expected<typename std::decay<Value>::type, Error>{
1397  in_place, static_cast<Value&&>(val)};
1398 }
1399 
1400 // Suppress comparability of Optional<T> with T, despite implicit conversion.
1401 template <class Value, class Error>
1402 bool operator==(const Expected<Value, Error>&, const Value& other) = delete;
1403 template <class Value, class Error>
1404 bool operator!=(const Expected<Value, Error>&, const Value& other) = delete;
1405 template <class Value, class Error>
1406 bool operator<(const Expected<Value, Error>&, const Value& other) = delete;
1407 template <class Value, class Error>
1408 bool operator<=(const Expected<Value, Error>&, const Value& other) = delete;
1409 template <class Value, class Error>
1410 bool operator>=(const Expected<Value, Error>&, const Value& other) = delete;
1411 template <class Value, class Error>
1412 bool operator>(const Expected<Value, Error>&, const Value& other) = delete;
1413 template <class Value, class Error>
1414 bool operator==(const Value& other, const Expected<Value, Error>&) = delete;
1415 template <class Value, class Error>
1416 bool operator!=(const Value& other, const Expected<Value, Error>&) = delete;
1417 template <class Value, class Error>
1418 bool operator<(const Value& other, const Expected<Value, Error>&) = delete;
1419 template <class Value, class Error>
1420 bool operator<=(const Value& other, const Expected<Value, Error>&) = delete;
1421 template <class Value, class Error>
1422 bool operator>=(const Value& other, const Expected<Value, Error>&) = delete;
1423 template <class Value, class Error>
1424 bool operator>(const Value& other, const Expected<Value, Error>&) = delete;
1425 
1426 } // namespace folly
1427 
1428 #if defined(__GNUC__) && !defined(__clang__)
1429 #pragma GCC diagnostic pop
1430 #endif
1431 
1432 #undef FOLLY_REQUIRES
1433 #undef FOLLY_REQUIRES_TRAILING
1434 
1435 // Enable the use of folly::Expected with `co_await`
1436 // Inspired by https://github.com/toby-allsopp/coroutine_monad
1437 #if FOLLY_HAS_COROUTINES
1438 #include <experimental/coroutine>
1439 
1440 namespace folly {
1441 namespace expected_detail {
1442 template <typename Value, typename Error>
1443 struct Promise;
1444 
1445 template <typename Value, typename Error>
1446 struct PromiseReturn {
1449  /* implicit */ PromiseReturn(Promise<Value, Error>& promise) noexcept
1450  : promise_(&promise) {
1451  promise_->value_ = &storage_;
1452  }
1453  PromiseReturn(PromiseReturn&& that) noexcept
1454  : PromiseReturn{*that.promise_} {}
1455  ~PromiseReturn() {}
1456  /* implicit */ operator Expected<Value, Error>() & {
1457  return std::move(*storage_);
1458  }
1459 };
1460 
1461 template <typename Value, typename Error>
1462 struct Promise {
1463  Optional<Expected<Value, Error>>* value_ = nullptr;
1464  Promise() = default;
1465  Promise(Promise const&) = delete;
1466  // This should work regardless of whether the compiler generates:
1467  // folly::Expected<Value, Error> retobj{ p.get_return_object(); } // MSVC
1468  // or:
1469  // auto retobj = p.get_return_object(); // clang
1470  PromiseReturn<Value, Error> get_return_object() noexcept {
1471  return *this;
1472  }
1473  std::experimental::suspend_never initial_suspend() const noexcept {
1474  return {};
1475  }
1476  std::experimental::suspend_never final_suspend() const {
1477  return {};
1478  }
1479  template <typename U>
1480  void return_value(U&& u) {
1481  value_->emplace(static_cast<U&&>(u));
1482  }
1483  void unhandled_exception() {
1484  // Technically, throwing from unhandled_exception is underspecified:
1485  // https://github.com/GorNishanov/CoroutineWording/issues/17
1486  throw;
1487  }
1488 };
1489 
1490 template <typename Value, typename Error>
1491 struct Awaitable {
1493 
1494  explicit Awaitable(Expected<Value, Error> o) : o_(std::move(o)) {}
1495 
1496  bool await_ready() const noexcept {
1497  return o_.hasValue();
1498  }
1499  Value await_resume() {
1500  return std::move(o_.value());
1501  }
1502 
1503  // Explicitly only allow suspension into a Promise
1504  template <typename U>
1505  void await_suspend(std::experimental::coroutine_handle<Promise<U, Error>> h) {
1506  *h.promise().value_ = makeUnexpected(std::move(o_.error()));
1507  // Abort the rest of the coroutine. resume() is not going to be called
1508  h.destroy();
1509  }
1510 };
1511 } // namespace expected_detail
1512 
1513 template <typename Value, typename Error>
1514 expected_detail::Awaitable<Value, Error>
1515 /* implicit */ operator co_await(Expected<Value, Error> o) {
1516  return expected_detail::Awaitable<Value, Error>{std::move(o)};
1517 }
1518 } // namespace folly
1519 
1520 // This makes folly::Expected<Value> useable as a coroutine return type...
1521 namespace std {
1522 namespace experimental {
1523 template <typename Value, typename Error, typename... Args>
1524 struct coroutine_traits<folly::Expected<Value, Error>, Args...> {
1525  using promise_type = folly::expected_detail::Promise<Value, Error>;
1526 };
1527 } // namespace experimental
1528 } // namespace std
1529 #endif // FOLLY_HAS_COROUTINES
constexpr bool hasValue() const noexcept
Definition: Expected.h:1107
constexpr ExpectedStorage(ValueTag, Vs &&...vs) noexcept(noexcept(Value(static_cast< Vs && >(vs)...)))
Definition: Expected.h:504
bool operator>(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1349
Base & base()&
Definition: Expected.h:895
*than *hazptr_holder h
Definition: Hazptr.h:116
Value && operator*()&&
Definition: Expected.h:1176
#define FOLLY_POP_WARNING
Definition: Portability.h:179
const Base & base() const &
Definition: Expected.h:898
void swap(Expected &that) noexcept(expected_detail::StrictAllOf< IsNothrowSwappable, Value, Error >::value)
Definition: Expected.h:1064
constexpr ExpectedStorage(EmptyTag) noexcept
Definition: Expected.h:198
StrictConjunction< std::is_nothrow_copy_constructible< T >, std::is_nothrow_copy_assignable< T >> IsNothrowCopyable
Definition: Expected.h:127
static Ret thenOrThrow_(This &&ex, Yes &&yes, No &&no)
Definition: Expected.h:622
void requireError() const
Definition: Expected.h:1282
ExpectedUnion(ExpectedUnion &&) noexcept
Definition: Expected.h:283
ExpectedUnion & operator=(ExpectedUnion &&) noexcept
Definition: Expected.h:287
#define FOLLY_PUSH_WARNING
Definition: Portability.h:178
constexpr Expected(in_place_t, std::initializer_list< U > il, Ts &&...ts) noexcept(noexcept(Value(std::declval< Ts >()...)))
Definition: Expected.h:965
Value & operator*()&
Definition: Expected.h:1172
void requireValue() const
Definition: Expected.h:1272
Expected & operator=(T &&val)
Definition: Expected.h:1030
auto then(Fns &&...fns)&&-> decltype(expected_detail::ExpectedHelper::then_(std::declval< Base && >(), std::declval< Fns >()...))
Definition: Expected.h:1225
CopyConstructible(const CopyConstructible &that) noexcept(Noexcept)
Definition: Expected.h:314
PskType type
Error && error()&&
Definition: Expected.h:1142
Expected() noexcept(noexcept(B{}))
Definition: Expected.h:923
const Value & value() const &
Definition: Expected.h:294
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Expected(const expected_detail::PromiseReturn< Value, Error > &p)
Definition: Expected.h:1050
#define LIKELY(x)
Definition: Likely.h:47
constexpr Expected(T &&val) noexcept(noexcept(Value(static_cast< T && >(val))))
Definition: Expected.h:950
STL namespace.
Value * operator->()
Definition: Expected.h:1184
constexpr Unexpected(const Error &err)
Definition: Expected.h:715
double val
Definition: String.cpp:273
constexpr ExpectedUnion(ErrorTag, Es &&...es) noexcept(noexcept(Error(static_cast< Es && >(es)...)))
Definition: Expected.h:279
static constexpr Expected< T, Error > return_(T t)
Definition: Expected.h:574
const Value * get_pointer() const &noexcept
Definition: Expected.h:1188
constexpr Expected< typename std::decay< Value >::type, Error > makeExpected(Value &&)
Definition: Expected.h:1394
folly::std T
static FOLLY_PUSH_WARNING auto then_(This &&ex, Fn &&fn, Fns &&...fns) -> decltype(T::then_(T::template return_< E >((std::declval< Fn >()(std::declval< This >().value()), unit)), std::declval< Fns >()...))
Definition: Expected.h:600
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
#define FOLLY_EXPORT
Definition: CPortability.h:133
const Value * operator->() const
Definition: Expected.h:1180
in_place_tag in_place(in_place_tag={})
Definition: Utility.h:235
requires E e noexcept(noexcept(s.error(std::move(e))))
BadExpectedAccess operator()(E &&err) const
Definition: Expected.h:748
in_place_tag(&)(in_place_tag) in_place_t
Definition: Utility.h:229
constexpr ExpectedStorage(ValueTag, Vs &&...vs) noexcept(noexcept(Value(static_cast< Vs && >(vs)...)))
Definition: Expected.h:201
CopyAssignable & operator=(const CopyAssignable &that) noexcept(Noexcept)
Definition: Expected.h:356
constexpr ExpectedUnion(EmptyTag) noexcept
Definition: Expected.h:273
requires And< SemiMovable< VN >... > &&SemiMovable< E > auto error(E e)
Definition: error.h:48
constexpr bool hasError() const noexcept
Definition: Expected.h:1111
StrictConjunction< std::is_nothrow_move_constructible< T >, std::is_nothrow_move_assignable< T >> IsNothrowMovable
Definition: Expected.h:132
Error & error()&
Definition: Expected.h:735
constexpr Unexpected(Error &&err)
Definition: Expected.h:716
typename std::remove_reference< Expected >::type::value_type ExpectedValueType
Definition: Expected.h:89
FOLLY_PUSH_WARNING RHS rhs
Definition: Traits.h:649
const Error & error() const &
Definition: Expected.h:255
constexpr Expected(in_place_t, Ts &&...ts) noexcept(noexcept(Value(std::declval< Ts >()...)))
Definition: Expected.h:956
Value * get_pointer()&noexcept
Definition: Expected.h:1192
constexpr StorageType getStorageType()
Definition: Expected.h:172
Value value_or(U &&dflt) const &
Definition: Expected.h:1149
auto doEmplaceAssign(int, T &t, U &&u) -> decltype(void(t=static_cast< U && >(u)))
Definition: Expected.h:140
ExpectedUnion(const ExpectedUnion &)
Definition: Expected.h:282
const Value & value() const &
Definition: Expected.h:241
bool operator!=(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
Definition: Expected.h:766
#define FOLLY_MSVC_DISABLE_WARNING(warningNumber)
Definition: Portability.h:183
Value & value()&
Definition: Expected.h:1122
const Error & error() const &
Definition: Expected.h:303
MoveAssignable & operator=(MoveAssignable &&that) noexcept(Noexcept)
Definition: Expected.h:378
bool Value(const T &value, M matcher)
constexpr Unexpected< typename std::decay< Error >::type > makeUnexpected(Error &&)
Definition: Expected.h:785
auto then(Fns &&...fns)&-> decltype(expected_detail::ExpectedHelper::then_(std::declval< Base & >(), std::declval< Fns >()...))
Definition: Expected.h:1214
expected_detail::Which which() const noexcept
Definition: Expected.h:1288
void swap(Expected< Value, Error > &lhs, Expected< Value, Error > &rhs) noexcept(expected_detail::StrictAllOf< IsNothrowSwappable, Value, Error >::value)
Definition: Expected.h:1368
expected_detail::UnexpectedTag unexpected(expected_detail::UnexpectedTag={})
Definition: Expected.h:656
ExpectedUnion & operator=(const ExpectedUnion &)
Definition: Expected.h:284
typename Unexpected< E >::MakeBadExpectedAccess MakeBadExpectedAccess
Definition: Expected.h:894
Promise< Unit > promise_
#define FOLLY_REQUIRES(...)
Definition: Expected.h:53
const Error & error() const &
Definition: Expected.h:1132
AtomicCounter< T, DeterministicAtomic > Base
constexpr Unit unit
Definition: Unit.h:45
error_stage Error
constexpr ExpectedStorage() noexcept(noexcept(E{}))
Definition: Expected.h:196
auto thenOrThrow(Yes &&yes, No &&no=No{})&-> decltype(std::declval< Yes >()(std::declval< Value & >()))
Definition: Expected.h:1250
const Value & value() const &
Definition: Expected.h:1117
static const char *const value
Definition: Conv.cpp:50
Value & emplace(Args &&...args)
Definition: Optional.h:231
Unexpected & operator=(Unexpected< Other > that)
Definition: Expected.h:728
constexpr ExpectedUnion(ValueTag, Vs &&...vs) noexcept(noexcept(Value(static_cast< Vs && >(vs)...)))
Definition: Expected.h:275
bool operator>=(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1358
const Value * get_pointer(const Expected< Value, Error > &ex) noexcept
Definition: Expected.h:1374
void swap(exception_wrapper &a, exception_wrapper &b) noexcept
constexpr ExpectedStorage(ErrorTag, Es &&...es) noexcept(noexcept(Error(static_cast< Es && >(es)...)))
Definition: Expected.h:508
bool operator==(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
Definition: Expected.h:758
bool operator<=(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1340
auto thenOrThrow(Yes &&yes, No &&no=No{}) const &-> decltype(std::declval< Yes >()(std::declval< const Value & >()))
Definition: Expected.h:1239
Expected & operator=(Expected< V, E > that)
Definition: Expected.h:1008
const
Definition: upload.py:398
Error && error()&&
Definition: Expected.h:741
void emplace(Ts &&...ts)
Definition: Expected.h:1057
typename std::remove_reference< Expected >::type::error_type ExpectedErrorType
Definition: Expected.h:96
constexpr ExpectedStorage(ErrorTag, Es &&...es) noexcept(noexcept(Error(static_cast< Es && >(es)...)))
Definition: Expected.h:205
Error & error()&
Definition: Expected.h:1137
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
const Error & error() const &
Definition: Expected.h:738
auto then(Fns &&...fns) const &-> decltype(expected_detail::ExpectedHelper::then_(std::declval< const Base & >(), std::declval< Fns >()...))
Definition: Expected.h:1202
static constexpr bool uninitializedByException() noexcept
Definition: Expected.h:209
Value value_or(U &&dflt)&&
Definition: Expected.h:1157
expected_detail::UnexpectedTag(&)(expected_detail::UnexpectedTag) unexpected_t
Definition: Expected.h:654
Base && base()&&
Definition: Expected.h:901
#define UNLIKELY(x)
Definition: Likely.h:48
Expected(Expected< V, E > that)
Definition: Expected.h:933
MoveConstructible(MoveConstructible &&that) noexcept(Noexcept)
Definition: Expected.h:335
static constexpr Expected< T, Error > return_(Expected< T, U > t)
Definition: Expected.h:582
Value && value()&&
Definition: Expected.h:1127
FOLLY_PUSH_WARNING FOLLY_MSVC_DISABLE_WARNING(4702) Error &error()&
Definition: Expected.h:251
const Value & operator*() const &
Definition: Expected.h:1168
constexpr Unexpected(Unexpected< Other > that)
Definition: Expected.h:720
std::enable_if< IsLessThanComparable< Value >::value, bool >::type operator<(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1321
static unordered_set< string > us
FOLLY_NOINLINE FOLLY_COLD void throw_exception(Ex &&ex)
Definition: Exception.h:32
auto thenOrThrow(Yes &&yes, No &&no=No{})&&-> decltype(std::declval< Yes >()(std::declval< Value && >()))
Definition: Expected.h:1261
#define FOLLY_REQUIRES_TRAILING(...)
Definition: Expected.h:51