2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * Like folly::Optional, but can store a value *or* and error.
20 * @author Eric Niebler (eniebler@fb.com)
26 #include <initializer_list>
29 #include <type_traits>
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>
38 #define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__)
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__)), \
46 #define FOLLY_REQUIRES_TRAILING(...) , FOLLY_REQUIRES_IMPL(__VA_ARGS__)
48 #define FOLLY_REQUIRES(...) template <FOLLY_REQUIRES_IMPL(__VA_ARGS__)>
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.
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"
64 * Forward declarations
66 template <class Error>
69 template <class Error>
70 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(Error&&);
72 template <class Value, class Error>
75 template <class Error, class Value>
76 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
80 * Alias for an Expected type's assiciated value_type
82 template <class Expected>
83 using ExpectedValueType =
84 typename std::remove_reference<Expected>::type::value_type;
87 * Alias for an Expected type's assiciated error_type
89 template <class Expected>
90 using ExpectedErrorType =
91 typename std::remove_reference<Expected>::type::error_type;
94 namespace expected_detail {
96 // MSVC 2015 can't handle the StrictConjunction, so we have
97 // to use std::conjunction instead.
98 template <template <class...> class Trait, class... Ts>
99 using StrictAllOf = std::conjunction<Trait<Ts>...>;
101 template <template <class...> class Trait, class... Ts>
102 using StrictAllOf = StrictConjunction<Trait<Ts>...>;
106 using IsCopyable = StrictConjunction<
107 std::is_copy_constructible<T>,
108 std::is_copy_assignable<T>>;
111 using IsMovable = StrictConjunction<
112 std::is_move_constructible<T>,
113 std::is_move_assignable<T>>;
116 using IsNothrowCopyable = StrictConjunction<
117 std::is_nothrow_copy_constructible<T>,
118 std::is_nothrow_copy_assignable<T>>;
121 using IsNothrowMovable = StrictConjunction<
122 std::is_nothrow_move_constructible<T>,
123 std::is_nothrow_move_assignable<T>>;
125 template <class From, class To>
126 using IsConvertible = StrictConjunction<
127 std::is_constructible<To, From>,
128 std::is_assignable<To&, From>>;
130 template <class T, class U>
131 auto doEmplaceAssign(int, T& t, U&& u) -> decltype(void(t = (U &&)u)) {
135 template <class T, class U>
136 auto doEmplaceAssign(long, T& t, U&& u) -> decltype(void(T((U &&)u))) {
138 ::new ((void*)std::addressof(t)) T((U &&)u);
141 template <class T, class... Us>
142 auto doEmplaceAssign(int, T& t, Us&&... us)
143 -> decltype(void(t = T((Us &&)us...))) {
147 template <class T, class... Us>
148 auto doEmplaceAssign(long, T& t, Us&&... us)
149 -> decltype(void(T((Us &&)us...))) {
151 ::new ((void*)std::addressof(t)) T((Us &&)us...);
157 enum class Which : unsigned char { eEmpty, eValue, eError };
158 enum class StorageType { ePODStruct, ePODUnion, eUnion };
160 template <class Value, class Error>
161 constexpr StorageType getStorageType() {
162 return StrictAllOf<IsTriviallyCopyable, Value, Error>::value
163 ? (sizeof(std::pair<Value, Error>) <= sizeof(void * [2]) &&
164 StrictAllOf<std::is_trivial, Value, Error>::value
165 ? StorageType::ePODStruct
166 : StorageType::ePODUnion)
167 : StorageType::eUnion;
173 StorageType = expected_detail::getStorageType<Value, Error>()> // ePODUnion
174 struct ExpectedStorage {
175 using value_type = Value;
176 using error_type = Error;
184 template <class E = Error, class = decltype(E{})>
185 constexpr ExpectedStorage() noexcept(noexcept(E{}))
186 : error_{}, which_(Which::eError) {}
187 explicit constexpr ExpectedStorage(EmptyTag) noexcept
188 : ch_{}, which_(Which::eEmpty) {}
189 template <class... Vs>
190 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
191 noexcept(Value(static_cast<Vs&&>(vs)...)))
192 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
193 template <class... Es>
194 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
195 noexcept(Error(static_cast<Es&&>(es)...)))
196 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
197 void clear() noexcept {}
198 static constexpr bool uninitializedByException() noexcept {
199 // Although which_ may temporarily be eEmpty during construction, it
200 // is always either eValue or eError for a fully-constructed Expected.
203 template <class... Vs>
204 void assignValue(Vs&&... vs) {
205 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
206 which_ = Which::eValue;
208 template <class... Es>
209 void assignError(Es&&... es) {
210 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
211 which_ = Which::eError;
213 template <class Other>
214 void assign(Other&& that) {
215 switch (that.which_) {
217 this->assignValue(static_cast<Other&&>(that).value());
220 this->assignError(static_cast<Other&&>(that).error());
230 const Value& value() const& {
234 return std::move(value_);
236 // TODO (t17322426): remove when VS2015 support is deprecated
237 // VS2015 static analyzer incorrectly flags these as unreachable in certain
238 // circumstances. VS2017 does not have this problem on the same code.
240 FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
244 const Error& error() const& {
248 return std::move(error_);
253 template <class Value, class Error>
254 struct ExpectedUnion {
260 Which which_ = Which::eEmpty;
262 explicit constexpr ExpectedUnion(EmptyTag) noexcept {}
263 template <class... Vs>
264 explicit constexpr ExpectedUnion(ValueTag, Vs&&... vs) noexcept(
265 noexcept(Value(static_cast<Vs&&>(vs)...)))
266 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
267 template <class... Es>
268 explicit constexpr ExpectedUnion(ErrorTag, Es&&... es) noexcept(
269 noexcept(Error(static_cast<Es&&>(es)...)))
270 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
271 ExpectedUnion(const ExpectedUnion&) {}
272 ExpectedUnion(ExpectedUnion&&) noexcept {}
273 ExpectedUnion& operator=(const ExpectedUnion&) {
276 ExpectedUnion& operator=(ExpectedUnion&&) noexcept {
283 const Value& value() const& {
287 return std::move(value_);
292 const Error& error() const& {
296 return std::move(error_);
300 template <class Derived, bool, bool Noexcept>
301 struct CopyConstructible {
302 constexpr CopyConstructible() = default;
303 CopyConstructible(const CopyConstructible& that) noexcept(Noexcept) {
304 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
306 constexpr CopyConstructible(CopyConstructible&&) = default;
307 CopyConstructible& operator=(const CopyConstructible&) = default;
308 CopyConstructible& operator=(CopyConstructible&&) = default;
311 template <class Derived, bool Noexcept>
312 struct CopyConstructible<Derived, false, Noexcept> {
313 constexpr CopyConstructible() = default;
314 CopyConstructible(const CopyConstructible&) = delete;
315 constexpr CopyConstructible(CopyConstructible&&) = default;
316 CopyConstructible& operator=(const CopyConstructible&) = default;
317 CopyConstructible& operator=(CopyConstructible&&) = default;
320 template <class Derived, bool, bool Noexcept>
321 struct MoveConstructible {
322 constexpr MoveConstructible() = default;
323 constexpr MoveConstructible(const MoveConstructible&) = default;
324 MoveConstructible(MoveConstructible&& that) noexcept(Noexcept) {
325 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
327 MoveConstructible& operator=(const MoveConstructible&) = default;
328 MoveConstructible& operator=(MoveConstructible&&) = default;
331 template <class Derived, bool Noexcept>
332 struct MoveConstructible<Derived, false, Noexcept> {
333 constexpr MoveConstructible() = default;
334 constexpr MoveConstructible(const MoveConstructible&) = default;
335 MoveConstructible(MoveConstructible&&) = delete;
336 MoveConstructible& operator=(const MoveConstructible&) = default;
337 MoveConstructible& operator=(MoveConstructible&&) = default;
340 template <class Derived, bool, bool Noexcept>
341 struct CopyAssignable {
342 constexpr CopyAssignable() = default;
343 constexpr CopyAssignable(const CopyAssignable&) = default;
344 constexpr CopyAssignable(CopyAssignable&&) = default;
345 CopyAssignable& operator=(const CopyAssignable& that) noexcept(Noexcept) {
346 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
349 CopyAssignable& operator=(CopyAssignable&&) = default;
352 template <class Derived, bool Noexcept>
353 struct CopyAssignable<Derived, false, Noexcept> {
354 constexpr CopyAssignable() = default;
355 constexpr CopyAssignable(const CopyAssignable&) = default;
356 constexpr CopyAssignable(CopyAssignable&&) = default;
357 CopyAssignable& operator=(const CopyAssignable&) = delete;
358 CopyAssignable& operator=(CopyAssignable&&) = default;
361 template <class Derived, bool, bool Noexcept>
362 struct MoveAssignable {
363 constexpr MoveAssignable() = default;
364 constexpr MoveAssignable(const MoveAssignable&) = default;
365 constexpr MoveAssignable(MoveAssignable&&) = default;
366 MoveAssignable& operator=(const MoveAssignable&) = default;
367 MoveAssignable& operator=(MoveAssignable&& that) noexcept(Noexcept) {
368 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
373 template <class Derived, bool Noexcept>
374 struct MoveAssignable<Derived, false, Noexcept> {
375 constexpr MoveAssignable() = default;
376 constexpr MoveAssignable(const MoveAssignable&) = default;
377 constexpr MoveAssignable(MoveAssignable&&) = default;
378 MoveAssignable& operator=(const MoveAssignable&) = default;
379 MoveAssignable& operator=(MoveAssignable&& that) = delete;
382 template <class Value, class Error>
383 struct ExpectedStorage<Value, Error, StorageType::eUnion>
384 : ExpectedUnion<Value, Error>,
386 ExpectedStorage<Value, Error, StorageType::eUnion>,
387 StrictAllOf<std::is_copy_constructible, Value, Error>::value,
388 StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::value>,
390 ExpectedStorage<Value, Error, StorageType::eUnion>,
391 StrictAllOf<std::is_move_constructible, Value, Error>::value,
392 StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::value>,
394 ExpectedStorage<Value, Error, StorageType::eUnion>,
395 StrictAllOf<IsCopyable, Value, Error>::value,
396 StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
398 ExpectedStorage<Value, Error, StorageType::eUnion>,
399 StrictAllOf<IsMovable, Value, Error>::value,
400 StrictAllOf<IsNothrowMovable, Value, Error>::value> {
401 using value_type = Value;
402 using error_type = Error;
403 using Base = ExpectedUnion<Value, Error>;
404 template <class E = Error, class = decltype(E{})>
405 constexpr ExpectedStorage() noexcept(noexcept(E{})) : Base{ErrorTag{}} {}
406 ExpectedStorage(const ExpectedStorage&) = default;
407 ExpectedStorage(ExpectedStorage&&) = default;
408 ExpectedStorage& operator=(const ExpectedStorage&) = default;
409 ExpectedStorage& operator=(ExpectedStorage&&) = default;
410 using ExpectedUnion<Value, Error>::ExpectedUnion;
414 void clear() noexcept {
415 switch (this->which_) {
417 this->value().~Value();
420 this->error().~Error();
425 this->which_ = Which::eEmpty;
427 bool uninitializedByException() const noexcept {
428 return this->which_ == Which::eEmpty;
430 template <class... Vs>
431 void assignValue(Vs&&... vs) {
432 if (this->which_ == Which::eValue) {
433 expected_detail::doEmplaceAssign(
434 0, this->value(), static_cast<Vs&&>(vs)...);
437 ::new ((void*)std::addressof(this->value()))
438 Value(static_cast<Vs&&>(vs)...);
439 this->which_ = Which::eValue;
442 template <class... Es>
443 void assignError(Es&&... es) {
444 if (this->which_ == Which::eError) {
445 expected_detail::doEmplaceAssign(
446 0, this->error(), static_cast<Es&&>(es)...);
449 ::new ((void*)std::addressof(this->error()))
450 Error(static_cast<Es&&>(es)...);
451 this->which_ = Which::eError;
454 bool isSelfAssign(const ExpectedStorage* that) const {
457 constexpr bool isSelfAssign(const void*) const {
460 template <class Other>
461 void assign(Other&& that) {
462 if (isSelfAssign(&that))
464 switch (that.which_) {
466 this->assignValue(static_cast<Other&&>(that).value());
469 this->assignError(static_cast<Other&&>(that).error());
478 // For small (pointer-sized) trivial types, a struct is faster than a union.
479 template <class Value, class Error>
480 struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
481 using value_type = Value;
482 using error_type = Error;
487 constexpr ExpectedStorage() noexcept
488 : which_(Which::eError), error_{}, value_{} {}
489 explicit constexpr ExpectedStorage(EmptyTag) noexcept
490 : which_(Which::eEmpty), error_{}, value_{} {}
491 template <class... Vs>
492 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
493 noexcept(Value(static_cast<Vs&&>(vs)...)))
494 : which_(Which::eValue), error_{}, value_(static_cast<Vs&&>(vs)...) {}
495 template <class... Es>
496 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
497 noexcept(Error(static_cast<Es&&>(es)...)))
498 : which_(Which::eError), error_(static_cast<Es&&>(es)...), value_{} {}
499 void clear() noexcept {}
500 constexpr static bool uninitializedByException() noexcept {
503 template <class... Vs>
504 void assignValue(Vs&&... vs) {
505 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
506 which_ = Which::eValue;
508 template <class... Es>
509 void assignError(Es&&... es) {
510 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
511 which_ = Which::eError;
513 template <class Other>
514 void assign(Other&& that) {
515 switch (that.which_) {
517 this->assignValue(static_cast<Other&&>(that).value());
520 this->assignError(static_cast<Other&&>(that).error());
530 const Value& value() const& {
534 return std::move(value_);
536 // TODO (t17322426): remove when VS2015 support is deprecated
537 // VS2015 static analyzer incorrectly flags these as unreachable in certain
538 // circumstances. VS2017 does not have this problem on the same code.
540 FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
544 const Error& error() const& {
548 return std::move(error_);
553 namespace expected_detail_ExpectedHelper {
554 // Tricky hack so that Expected::then can handle lambdas that return void
556 inline T&& operator,(T&& t, Unit) noexcept {
557 return static_cast<T&&>(t);
560 struct ExpectedHelper {
561 template <class Error, class T>
562 static constexpr Expected<T, Error> return_(T t) {
563 return folly::makeExpected<Error>(t);
568 class U FOLLY_REQUIRES_TRAILING(
569 expected_detail::IsConvertible<U&&, Error>::value)>
570 static constexpr Expected<T, Error> return_(Expected<T, U> t) {
574 template <class This>
575 static typename std::decay<This>::type then_(This&& ex) {
576 return static_cast<This&&>(ex);
580 // Don't warn about not using the overloaded comma operator.
581 FOLLY_MSVC_DISABLE_WARNING(4913)
586 class E = ExpectedErrorType<This>,
587 class T = ExpectedHelper>
588 static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
589 T::template return_<E>(
590 (std::declval<Fn>()(std::declval<This>().value()), unit)),
591 std::declval<Fns>()...)) {
592 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
594 T::template return_<E>(
595 // Uses the comma operator defined above IFF the lambda
597 (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
598 static_cast<Fns&&>(fns)...);
599 return makeUnexpected(static_cast<This&&>(ex).error());
606 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
607 class Err = decltype(std::declval<No>()(std::declval<This>().error()))
608 FOLLY_REQUIRES_TRAILING(!std::is_void<Err>::value)>
609 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
610 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
611 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
612 throw static_cast<No&&>(no)(static_cast<This&&>(ex).error());
619 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
620 class Err = decltype(std::declval<No>()(std::declval<This&>().error()))
621 FOLLY_REQUIRES_TRAILING(std::is_void<Err>::value)>
622 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
623 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
624 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
625 static_cast<No&&>(no)(ex.error());
626 throw typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess()(
627 static_cast<This&&>(ex).error());
632 /* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
634 struct UnexpectedTag {};
636 } // namespace expected_detail
639 expected_detail::UnexpectedTag (&)(expected_detail::UnexpectedTag);
641 inline expected_detail::UnexpectedTag unexpected(
642 expected_detail::UnexpectedTag = {}) {
647 * An exception type thrown by Expected on catastrophic logic errors.
649 class BadExpectedAccess : public std::logic_error {
651 BadExpectedAccess() : std::logic_error("bad Expected access") {}
655 * Unexpected - a helper type used to disambiguate the construction of
656 * Expected objects in the error state.
658 template <class Error>
659 class Unexpected final {
661 friend class Unexpected;
662 template <class V, class E>
663 friend class Expected;
664 friend struct expected_detail::ExpectedHelper;
668 * Unexpected::BadExpectedAccess - An exception type thrown by Expected
669 * when the user tries to access the nested value but the Expected object is
670 * actually storing an error code.
672 class BadExpectedAccess : public folly::BadExpectedAccess {
674 explicit BadExpectedAccess(Error err)
675 : folly::BadExpectedAccess{}, error_(std::move(err)) {}
677 * The error code that was held by the Expected object when the user
678 * erroneously requested the value.
680 Error error() const {
691 Unexpected() = default;
692 Unexpected(const Unexpected&) = default;
693 Unexpected(Unexpected&&) = default;
694 Unexpected& operator=(const Unexpected&) = default;
695 Unexpected& operator=(Unexpected&&) = default;
696 constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {}
697 constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {}
699 template <class Other FOLLY_REQUIRES_TRAILING(
700 std::is_constructible<Error, Other&&>::value)>
701 constexpr /* implicit */ Unexpected(Unexpected<Other> that)
702 : error_(std::move(that.error())) {}
707 template <class Other FOLLY_REQUIRES_TRAILING(
708 std::is_assignable<Error&, Other&&>::value)>
709 Unexpected& operator=(Unexpected<Other> that) {
710 error_ = std::move(that.error());
719 const Error& error() const& {
723 return std::move(error_);
727 struct MakeBadExpectedAccess {
729 BadExpectedAccess operator()(E&& err) const {
730 return BadExpectedAccess(static_cast<E&&>(err));
738 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
739 inline bool operator==(
740 const Unexpected<Error>& lhs,
741 const Unexpected<Error>& rhs) {
742 return lhs.error() == rhs.error();
746 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
747 inline bool operator!=(
748 const Unexpected<Error>& lhs,
749 const Unexpected<Error>& rhs) {
750 return !(lhs == rhs);
754 * For constructing an Unexpected object from an error code. Unexpected objects
755 * are implicitly convertible to Expected object in the error state. Usage is
758 * enum class MyErrorCode { BAD_ERROR, WORSE_ERROR };
759 * Expected<int, MyErrorCode> myAPI() {
761 * return i ? makeExpected<MyErrorCode>(i)
762 * : makeUnexpected(MyErrorCode::BAD_ERROR);
765 template <class Error>
766 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(
768 return Unexpected<typename std::decay<Error>::type>{
769 static_cast<Error&&>(err)};
773 * Expected - For holding a value or an error. Useful as an alternative to
774 * exceptions, for APIs where throwing on failure would be too expensive.
776 * Expected<Value, Error> is a variant over the types Value and Error.
778 * Expected does not offer support for references. Use
779 * Expected<std::reference_wrapper<T>, Error> if your API needs to return a
780 * reference or an error.
782 * Expected offers a continuation-based interface to reduce the boilerplate
783 * of checking error codes. The Expected::then member function takes a lambda
784 * that is to execute should the Expected object contain a value. The return
785 * value of the lambda is wrapped in an Expected and returned. If the lambda is
786 * not executed because the Expected contains an error, the error is returned
787 * immediately in a new Expected object.
789 * Expected<int, Error> funcTheFirst();
790 * Expected<std::string, Error> funcTheSecond() {
791 * return funcTheFirst().then([](int i) { return std::to_string(i); });
794 * The above line of code could more verbosely written as:
796 * Expected<std::string, Error> funcTheSecond() {
797 * if (auto ex = funcTheFirst()) {
798 * return std::to_string(*ex);
800 * return makeUnexpected(ex.error());
803 * Continuations can chain, like:
805 * Expected<D, Error> maybeD = someFunc()
806 * .then([](A a){return B(a);})
807 * .then([](B b){return C(b);})
808 * .then([](C c){return D(c);});
810 * To avoid the redundant error checking that would happen if a call at the
811 * front of the chain returns an error, these call chains can be collaped into
812 * a single call to .then:
814 * Expected<D, Error> maybeD = someFunc()
815 * .then([](A a){return B(a);},
816 * [](B b){return C(b);},
817 * [](C c){return D(c);});
819 * The result of .then() is wrapped into Expected< ~, Error > if it isn't
820 * of that form already. Consider the following code:
822 * extern Expected<std::string, Error> readLineFromIO();
823 * extern Expected<int, Error> parseInt(std::string);
824 * extern int increment(int);
826 * Expected<int, Error> x = readLineFromIO().then(parseInt).then(increment);
828 * From the code above, we see that .then() works both with functions that
829 * return an Expected< ~, Error > (like parseInt) and with ones that return
830 * a plain value (like increment). In the case of parseInt, .then() returns
831 * the result of parseInt as-is. In the case of increment, it wraps the int
832 * that increment returns into an Expected< int, Error >.
834 * Sometimes when using a continuation you would prefer an exception to be
835 * thrown for a value-less Expected. For that you can use .thenOrThrow, as
839 * .thenOrThrow([](A a){return B(a);});
841 * The above call to thenOrThrow will invoke the lambda if the Expected returned
842 * by someFunc() contains a value. Otherwise, it will throw an exception of type
843 * Unexpected<Error>::BadExpectedAccess. If you prefer it throw an exception of
844 * a different type, you can pass a second lambda to thenOrThrow:
847 * .thenOrThrow([](A a){return B(a);},
848 * [](Error e) {throw MyException(e);});
850 * Like C++17's std::variant, Expected offers the almost-never-empty guarantee;
851 * that is, an Expected<Value, Error> almost always contains either a Value or
852 * and Error. Partially-formed Expected objects occur when an assignment to
853 * an Expected object that would change the type of the contained object (Value-
854 * to-Error or vice versa) throws. Trying to access either the contained value
855 * or error object causes Expected to throw folly::BadExpectedAccess.
857 * Expected models OptionalPointee, so calling 'get_pointer(ex)' will return a
858 * pointer to nullptr if the 'ex' is in the error state, and a pointer to the
861 * Expected<int, Error> maybeInt = ...;
862 * if (int* v = get_pointer(maybeInt)) {
863 * cout << *v << endl;
866 template <class Value, class Error>
867 class Expected final : expected_detail::ExpectedStorage<Value, Error> {
868 template <class, class>
869 friend class Expected;
870 template <class, class, expected_detail::StorageType>
871 friend struct expected_detail::ExpectedStorage;
872 friend struct expected_detail::ExpectedHelper;
873 using Base = expected_detail::ExpectedStorage<Value, Error>;
874 using MakeBadExpectedAccess =
875 typename Unexpected<Error>::MakeBadExpectedAccess;
879 const Base& base() const& {
883 return std::move(*this);
887 using value_type = Value;
888 using error_type = Error;
889 using IsTriviallyCopyable = typename expected_detail::
890 StrictAllOf<IsTriviallyCopyable, Value, Error>::type;
893 using rebind = Expected<U, Error>;
896 !std::is_reference<Value>::value,
897 "Expected may not be used with reference types");
899 !std::is_abstract<Value>::value,
900 "Expected may not be used with abstract types");
905 template <class B = Base, class = decltype(B{})>
906 Expected() noexcept(noexcept(B{})) : Base{} {}
907 Expected(const Expected& that) = default;
908 Expected(Expected&& that) = default;
912 class E FOLLY_REQUIRES_TRAILING(
913 !std::is_same<Expected<V, E>, Expected>::value &&
914 std::is_constructible<Value, V&&>::value &&
915 std::is_constructible<Error, E&&>::value)>
916 Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} {
917 *this = std::move(that);
920 FOLLY_REQUIRES(std::is_copy_constructible<Value>::value)
921 constexpr /* implicit */ Expected(const Value& val) noexcept(
922 noexcept(Value(val)))
923 : Base{expected_detail::ValueTag{}, val} {}
925 FOLLY_REQUIRES(std::is_move_constructible<Value>::value)
926 constexpr /* implicit */ Expected(Value&& val) noexcept(
927 noexcept(Value(std::move(val))))
928 : Base{expected_detail::ValueTag{}, std::move(val)} {}
930 template <class T FOLLY_REQUIRES_TRAILING(
931 std::is_convertible<T, Value>::value &&
932 !std::is_convertible<T, Error>::value)>
933 constexpr /* implicit */ Expected(T&& val) noexcept(
934 noexcept(Value(static_cast<T&&>(val))))
935 : Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {}
937 template <class... Ts FOLLY_REQUIRES_TRAILING(
938 std::is_constructible<Value, Ts&&...>::value)>
939 explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
940 noexcept(Value(std::declval<Ts>()...)))
941 : Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {}
945 class... Ts FOLLY_REQUIRES_TRAILING(
946 std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
948 explicit constexpr Expected(
950 std::initializer_list<U> il,
951 Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
952 : Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {}
954 // If overload resolution selects one of these deleted functions, that
955 // means you need to use makeUnexpected
956 /* implicit */ Expected(const Error&) = delete;
957 /* implicit */ Expected(Error&&) = delete;
959 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
960 constexpr Expected(unexpected_t, const Error& err) noexcept(
961 noexcept(Error(err)))
962 : Base{expected_detail::ErrorTag{}, err} {}
964 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
965 constexpr Expected(unexpected_t, Error&& err) noexcept(
966 noexcept(Error(std::move(err))))
967 : Base{expected_detail::ErrorTag{}, std::move(err)} {}
969 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
970 constexpr /* implicit */ Expected(const Unexpected<Error>& err) noexcept(
971 noexcept(Error(err.error())))
972 : Base{expected_detail::ErrorTag{}, err.error()} {}
974 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
975 constexpr /* implicit */ Expected(Unexpected<Error>&& err) noexcept(
976 noexcept(Error(std::move(err.error()))))
977 : Base{expected_detail::ErrorTag{}, std::move(err.error())} {}
980 * Assignment operators
982 Expected& operator=(const Expected& that) = default;
983 Expected& operator=(Expected&& that) = default;
987 class E FOLLY_REQUIRES_TRAILING(
988 !std::is_same<Expected<V, E>, Expected>::value &&
989 expected_detail::IsConvertible<V&&, Value>::value &&
990 expected_detail::IsConvertible<E&&, Error>::value)>
991 Expected& operator=(Expected<V, E> that) {
992 this->assign(std::move(that));
996 FOLLY_REQUIRES(expected_detail::IsCopyable<Value>::value)
997 Expected& operator=(const Value& val) noexcept(
998 expected_detail::IsNothrowCopyable<Value>::value) {
999 this->assignValue(val);
1003 FOLLY_REQUIRES(expected_detail::IsMovable<Value>::value)
1004 Expected& operator=(Value&& val) noexcept(
1005 expected_detail::IsNothrowMovable<Value>::value) {
1006 this->assignValue(std::move(val));
1010 template <class T FOLLY_REQUIRES_TRAILING(
1011 std::is_convertible<T, Value>::value &&
1012 !std::is_convertible<T, Error>::value)>
1013 Expected& operator=(T&& val) {
1014 this->assignValue(static_cast<T&&>(val));
1018 FOLLY_REQUIRES(expected_detail::IsCopyable<Error>::value)
1019 Expected& operator=(const Unexpected<Error>& err) noexcept(
1020 expected_detail::IsNothrowCopyable<Error>::value) {
1021 this->assignError(err.error());
1025 FOLLY_REQUIRES(expected_detail::IsMovable<Error>::value)
1026 Expected& operator=(Unexpected<Error>&& err) noexcept(
1027 expected_detail::IsNothrowMovable<Error>::value) {
1028 this->assignError(std::move(err.error()));
1032 template <class... Ts FOLLY_REQUIRES_TRAILING(
1033 std::is_constructible<Value, Ts&&...>::value)>
1034 void emplace(Ts&&... ts) {
1035 this->assignValue(static_cast<Ts&&>(ts)...);
1041 void swap(Expected& that) noexcept(
1042 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1043 if (this->uninitializedByException() || that.uninitializedByException())
1044 throw BadExpectedAccess();
1048 swap(this->value_, that.value_);
1050 Error e(std::move(that.error_));
1051 that.assignValue(std::move(this->value_));
1052 this->assignError(std::move(e));
1056 swap(this->error_, that.error_);
1058 Error e(std::move(this->error_));
1059 this->assignValue(std::move(that.value_));
1060 that.assignError(std::move(e));
1065 // If overload resolution selects one of these deleted functions, that
1066 // means you need to use makeUnexpected
1067 /* implicit */ Expected& operator=(const Error&) = delete;
1068 /* implicit */ Expected& operator=(Error&&) = delete;
1071 * Relational Operators
1073 template <class Val, class Err>
1074 friend typename std::enable_if<IsEqualityComparable<Val>::value, bool>::type
1075 operator==(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1076 template <class Val, class Err>
1077 friend typename std::enable_if<IsLessThanComparable<Val>::value, bool>::type
1078 operator<(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1083 constexpr bool hasValue() const noexcept {
1084 return expected_detail::Which::eValue == this->which_;
1087 constexpr bool hasError() const noexcept {
1088 return expected_detail::Which::eError == this->which_;
1091 using Base::uninitializedByException;
1093 const Value& value() const& {
1095 return this->Base::value();
1100 return this->Base::value();
1103 Value&& value() && {
1105 return std::move(this->Base::value());
1108 const Error& error() const& {
1110 return this->Base::error();
1115 return this->Base::error();
1118 Error&& error() && {
1120 return std::move(this->Base::error());
1123 // Return a copy of the value if set, or a given default if not.
1125 Value value_or(U&& dflt) const& {
1126 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1127 return this->value_;
1129 return static_cast<U&&>(dflt);
1133 Value value_or(U&& dflt) && {
1134 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1135 return std::move(this->value_);
1137 return static_cast<U&&>(dflt);
1140 explicit constexpr operator bool() const noexcept {
1144 const Value& operator*() const& {
1145 return this->value();
1148 Value& operator*() & {
1149 return this->value();
1152 Value&& operator*() && {
1153 return std::move(this->value());
1156 const Value* operator->() const {
1157 return std::addressof(this->value());
1160 Value* operator->() {
1161 return std::addressof(this->value());
1164 const Value* get_pointer() const& noexcept {
1165 return hasValue() ? std::addressof(this->value_) : nullptr;
1168 Value* get_pointer() & noexcept {
1169 return hasValue() ? std::addressof(this->value_) : nullptr;
1172 Value* get_pointer() && = delete;
1177 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1178 auto then(Fns&&... fns) const& -> decltype(
1179 expected_detail::ExpectedHelper::then_(
1180 std::declval<const Base&>(),
1181 std::declval<Fns>()...)) {
1182 if (this->uninitializedByException())
1183 throw BadExpectedAccess();
1184 return expected_detail::ExpectedHelper::then_(
1185 base(), static_cast<Fns&&>(fns)...);
1188 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1189 auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1190 std::declval<Base&>(),
1191 std::declval<Fns>()...)) {
1192 if (this->uninitializedByException())
1193 throw BadExpectedAccess();
1194 return expected_detail::ExpectedHelper::then_(
1195 base(), static_cast<Fns&&>(fns)...);
1198 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1199 auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1200 std::declval<Base&&>(),
1201 std::declval<Fns>()...)) {
1202 if (this->uninitializedByException())
1203 throw BadExpectedAccess();
1204 return expected_detail::ExpectedHelper::then_(
1205 std::move(base()), static_cast<Fns&&>(fns)...);
1211 template <class Yes, class No = MakeBadExpectedAccess>
1212 auto thenOrThrow(Yes&& yes, No&& no = No{}) const& -> decltype(
1213 std::declval<Yes>()(std::declval<const Value&>())) {
1214 using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1215 if (this->uninitializedByException())
1216 throw BadExpectedAccess();
1217 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1218 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1221 template <class Yes, class No = MakeBadExpectedAccess>
1222 auto thenOrThrow(Yes&& yes, No&& no = No{}) & -> decltype(
1223 std::declval<Yes>()(std::declval<Value&>())) {
1224 using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1225 if (this->uninitializedByException())
1226 throw BadExpectedAccess();
1227 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1228 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1231 template <class Yes, class No = MakeBadExpectedAccess>
1232 auto thenOrThrow(Yes&& yes, No&& no = No{}) && -> decltype(
1233 std::declval<Yes>()(std::declval<Value&&>())) {
1234 using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1235 if (this->uninitializedByException())
1236 throw BadExpectedAccess();
1237 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1238 std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1242 void requireValue() const {
1243 if (UNLIKELY(!hasValue())) {
1244 if (LIKELY(hasError()))
1245 throw typename Unexpected<Error>::BadExpectedAccess(this->error_);
1246 throw BadExpectedAccess();
1250 void requireError() const {
1251 if (UNLIKELY(!hasError())) {
1252 throw BadExpectedAccess();
1256 expected_detail::Which which() const noexcept {
1257 return this->which_;
1261 template <class Value, class Error>
1262 inline typename std::enable_if<IsEqualityComparable<Value>::value, bool>::type
1264 const Expected<Value, Error>& lhs,
1265 const Expected<Value, Error>& rhs) {
1266 if (UNLIKELY(lhs.which_ != rhs.which_))
1267 return UNLIKELY(lhs.uninitializedByException()) ? false
1268 : throw BadExpectedAccess();
1269 if (UNLIKELY(lhs.uninitializedByException()))
1270 throw BadExpectedAccess();
1271 if (UNLIKELY(lhs.hasError()))
1272 return true; // All error states are considered equal
1273 return lhs.value_ == rhs.value_;
1278 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Value>::value)>
1279 inline bool operator!=(
1280 const Expected<Value, Error>& lhs,
1281 const Expected<Value, Error>& rhs) {
1282 return !(rhs == lhs);
1285 template <class Value, class Error>
1286 inline typename std::enable_if<IsLessThanComparable<Value>::value, bool>::type
1288 const Expected<Value, Error>& lhs,
1289 const Expected<Value, Error>& rhs) {
1291 lhs.uninitializedByException() || rhs.uninitializedByException()))
1292 throw BadExpectedAccess();
1293 if (UNLIKELY(lhs.hasError()))
1294 return !rhs.hasError();
1295 if (UNLIKELY(rhs.hasError()))
1297 return lhs.value_ < rhs.value_;
1302 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1303 inline bool operator<=(
1304 const Expected<Value, Error>& lhs,
1305 const Expected<Value, Error>& rhs) {
1306 return !(rhs < lhs);
1311 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1312 inline bool operator>(
1313 const Expected<Value, Error>& lhs,
1314 const Expected<Value, Error>& rhs) {
1320 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1321 inline bool operator>=(
1322 const Expected<Value, Error>& lhs,
1323 const Expected<Value, Error>& rhs) {
1324 return !(lhs < rhs);
1328 * swap Expected values
1330 template <class Error, class Value>
1331 void swap(Expected<Error, Value>& lhs, Expected<Value, Error>& rhs) noexcept(
1332 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1336 template <class Value, class Error>
1337 const Value* get_pointer(const Expected<Value, Error>& ex) noexcept {
1338 return ex.get_pointer();
1341 template <class Value, class Error>
1342 Value* get_pointer(Expected<Value, Error>& ex) noexcept {
1343 return ex.get_pointer();
1347 * For constructing an Expected object from a value, with the specified
1348 * Error type. Usage is as follows:
1350 * enum MyErrorCode { BAD_ERROR, WORSE_ERROR };
1351 * Expected<int, MyErrorCode> myAPI() {
1353 * return i ? makeExpected<MyErrorCode>(i) : makeUnexpected(BAD_ERROR);
1356 template <class Error, class Value>
1357 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
1359 return Expected<typename std::decay<Value>::type, Error>{
1360 in_place, static_cast<Value&&>(val)};
1363 // Suppress comparability of Optional<T> with T, despite implicit conversion.
1364 template <class Value, class Error>
1365 bool operator==(const Expected<Value, Error>&, const Value& other) = delete;
1366 template <class Value, class Error>
1367 bool operator!=(const Expected<Value, Error>&, const Value& other) = delete;
1368 template <class Value, class Error>
1369 bool operator<(const Expected<Value, Error>&, const Value& other) = delete;
1370 template <class Value, class Error>
1371 bool operator<=(const Expected<Value, Error>&, const Value& other) = delete;
1372 template <class Value, class Error>
1373 bool operator>=(const Expected<Value, Error>&, const Value& other) = delete;
1374 template <class Value, class Error>
1375 bool operator>(const Expected<Value, Error>&, const Value& other) = delete;
1376 template <class Value, class Error>
1377 bool operator==(const Value& other, const Expected<Value, Error>&) = delete;
1378 template <class Value, class Error>
1379 bool operator!=(const Value& other, const Expected<Value, Error>&) = delete;
1380 template <class Value, class Error>
1381 bool operator<(const Value& other, const Expected<Value, Error>&) = delete;
1382 template <class Value, class Error>
1383 bool operator<=(const Value& other, const Expected<Value, Error>&) = delete;
1384 template <class Value, class Error>
1385 bool operator>=(const Value& other, const Expected<Value, Error>&) = delete;
1386 template <class Value, class Error>
1387 bool operator>(const Value& other, const Expected<Value, Error>&) = delete;
1389 } // namespace folly
1391 #if defined(__GNUC__) && !defined(__clang__)
1392 #pragma GCC diagnostic pop
1395 #undef FOLLY_REQUIRES
1396 #undef FOLLY_REQUIRES_TRAILING