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* an error.
20 * @author Eric Niebler (eniebler@fb.com)
26 #include <initializer_list>
29 #include <type_traits>
32 #include <glog/logging.h>
34 #include <folly/CppAttributes.h>
35 #include <folly/Likely.h>
36 #include <folly/Optional.h>
37 #include <folly/Portability.h>
38 #include <folly/Preprocessor.h>
39 #include <folly/Traits.h>
40 #include <folly/Unit.h>
41 #include <folly/Utility.h>
42 #include <folly/lang/ColdClass.h>
44 #define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__)
46 #define FOLLY_REQUIRES_IMPL(...) \
47 bool FOLLY_EXPECTED_ID(Requires) = false, \
48 typename std::enable_if< \
49 (FOLLY_EXPECTED_ID(Requires) || static_cast<bool>(__VA_ARGS__)), \
52 #define FOLLY_REQUIRES_TRAILING(...) , FOLLY_REQUIRES_IMPL(__VA_ARGS__)
54 #define FOLLY_REQUIRES(...) template <FOLLY_REQUIRES_IMPL(__VA_ARGS__)>
57 * gcc-4.7 warns about use of uninitialized memory around the use of storage_
58 * even though this is explicitly initialized at each point.
60 #if defined(__GNUC__) && !defined(__clang__)
61 #pragma GCC diagnostic push
62 #pragma GCC diagnostic ignored "-Wuninitialized"
63 #pragma GCC diagnostic ignored "-Wpragmas"
64 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
70 * Forward declarations
72 template <class Error>
75 template <class Error>
76 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(Error&&);
78 template <class Value, class Error>
81 template <class Error, class Value>
82 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
86 * Alias for an Expected type's assiciated value_type
88 template <class Expected>
89 using ExpectedValueType =
90 typename std::remove_reference<Expected>::type::value_type;
93 * Alias for an Expected type's assiciated error_type
95 template <class Expected>
96 using ExpectedErrorType =
97 typename std::remove_reference<Expected>::type::error_type;
100 namespace expected_detail {
102 template <typename Value, typename Error>
103 struct PromiseReturn;
106 // MSVC 2015 can't handle the StrictConjunction, so we have
107 // to use std::conjunction instead.
108 template <template <class...> class Trait, class... Ts>
109 using StrictAllOf = std::conjunction<Trait<Ts>...>;
111 template <template <class...> class Trait, class... Ts>
112 using StrictAllOf = StrictConjunction<Trait<Ts>...>;
116 using IsCopyable = StrictConjunction<
117 std::is_copy_constructible<T>,
118 std::is_copy_assignable<T>>;
121 using IsMovable = StrictConjunction<
122 std::is_move_constructible<T>,
123 std::is_move_assignable<T>>;
126 using IsNothrowCopyable = StrictConjunction<
127 std::is_nothrow_copy_constructible<T>,
128 std::is_nothrow_copy_assignable<T>>;
131 using IsNothrowMovable = StrictConjunction<
132 std::is_nothrow_move_constructible<T>,
133 std::is_nothrow_move_assignable<T>>;
135 template <class From, class To>
136 using IsConvertible = StrictConjunction<
137 std::is_constructible<To, From>,
138 std::is_assignable<To&, From>>;
140 template <class T, class U>
141 auto doEmplaceAssign(int, T& t, U&& u) -> decltype(void(t = (U &&)u)) {
145 template <class T, class U>
146 auto doEmplaceAssign(long, T& t, U&& u) -> decltype(void(T((U &&)u))) {
148 ::new ((void*)std::addressof(t)) T((U &&)u);
151 template <class T, class... Us>
152 auto doEmplaceAssign(int, T& t, Us&&... us)
153 -> decltype(void(t = T((Us &&)us...))) {
157 template <class T, class... Us>
158 auto doEmplaceAssign(long, T& t, Us&&... us)
159 -> decltype(void(T((Us &&)us...))) {
161 ::new ((void*)std::addressof(t)) T((Us &&)us...);
167 enum class Which : unsigned char { eEmpty, eValue, eError };
168 enum class StorageType { ePODStruct, ePODUnion, eUnion };
170 template <class Value, class Error>
171 constexpr StorageType getStorageType() {
172 return StrictAllOf<IsTriviallyCopyable, Value, Error>::value
173 ? (sizeof(std::pair<Value, Error>) <= sizeof(void * [2]) &&
174 StrictAllOf<std::is_trivial, Value, Error>::value
175 ? StorageType::ePODStruct
176 : StorageType::ePODUnion)
177 : StorageType::eUnion;
183 StorageType = expected_detail::getStorageType<Value, Error>()> // ePODUnion
184 struct ExpectedStorage {
185 using value_type = Value;
186 using error_type = Error;
194 template <class E = Error, class = decltype(E{})>
195 constexpr ExpectedStorage() noexcept(noexcept(E{}))
196 : error_{}, which_(Which::eError) {}
197 explicit constexpr ExpectedStorage(EmptyTag) noexcept
198 : ch_{}, which_(Which::eEmpty) {}
199 template <class... Vs>
200 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
201 noexcept(Value(static_cast<Vs&&>(vs)...)))
202 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
203 template <class... Es>
204 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
205 noexcept(Error(static_cast<Es&&>(es)...)))
206 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
207 void clear() noexcept {}
208 static constexpr bool uninitializedByException() noexcept {
209 // Although which_ may temporarily be eEmpty during construction, it
210 // is always either eValue or eError for a fully-constructed Expected.
213 template <class... Vs>
214 void assignValue(Vs&&... vs) {
215 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
216 which_ = Which::eValue;
218 template <class... Es>
219 void assignError(Es&&... es) {
220 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
221 which_ = Which::eError;
223 template <class Other>
224 void assign(Other&& that) {
225 switch (that.which_) {
227 this->assignValue(static_cast<Other&&>(that).value());
230 this->assignError(static_cast<Other&&>(that).error());
240 const Value& value() const& {
244 return std::move(value_);
246 // TODO (t17322426): remove when VS2015 support is deprecated
247 // VS2015 static analyzer incorrectly flags these as unreachable in certain
248 // circumstances. VS2017 does not have this problem on the same code.
250 FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
254 const Error& error() const& {
258 return std::move(error_);
263 template <class Value, class Error>
264 struct ExpectedUnion {
270 Which which_ = Which::eEmpty;
272 explicit constexpr ExpectedUnion(EmptyTag) noexcept {}
273 template <class... Vs>
274 explicit constexpr ExpectedUnion(ValueTag, Vs&&... vs) noexcept(
275 noexcept(Value(static_cast<Vs&&>(vs)...)))
276 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
277 template <class... Es>
278 explicit constexpr ExpectedUnion(ErrorTag, Es&&... es) noexcept(
279 noexcept(Error(static_cast<Es&&>(es)...)))
280 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
281 ExpectedUnion(const ExpectedUnion&) {}
282 ExpectedUnion(ExpectedUnion&&) noexcept {}
283 ExpectedUnion& operator=(const ExpectedUnion&) {
286 ExpectedUnion& operator=(ExpectedUnion&&) noexcept {
293 const Value& value() const& {
297 return std::move(value_);
302 const Error& error() const& {
306 return std::move(error_);
310 template <class Derived, bool, bool Noexcept>
311 struct CopyConstructible {
312 constexpr CopyConstructible() = default;
313 CopyConstructible(const CopyConstructible& that) noexcept(Noexcept) {
314 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
316 constexpr CopyConstructible(CopyConstructible&&) = default;
317 CopyConstructible& operator=(const CopyConstructible&) = default;
318 CopyConstructible& operator=(CopyConstructible&&) = default;
321 template <class Derived, bool Noexcept>
322 struct CopyConstructible<Derived, false, Noexcept> {
323 constexpr CopyConstructible() = default;
324 CopyConstructible(const CopyConstructible&) = delete;
325 constexpr CopyConstructible(CopyConstructible&&) = default;
326 CopyConstructible& operator=(const CopyConstructible&) = default;
327 CopyConstructible& operator=(CopyConstructible&&) = default;
330 template <class Derived, bool, bool Noexcept>
331 struct MoveConstructible {
332 constexpr MoveConstructible() = default;
333 constexpr MoveConstructible(const MoveConstructible&) = default;
334 MoveConstructible(MoveConstructible&& that) noexcept(Noexcept) {
335 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
337 MoveConstructible& operator=(const MoveConstructible&) = default;
338 MoveConstructible& operator=(MoveConstructible&&) = default;
341 template <class Derived, bool Noexcept>
342 struct MoveConstructible<Derived, false, Noexcept> {
343 constexpr MoveConstructible() = default;
344 constexpr MoveConstructible(const MoveConstructible&) = default;
345 MoveConstructible(MoveConstructible&&) = delete;
346 MoveConstructible& operator=(const MoveConstructible&) = default;
347 MoveConstructible& operator=(MoveConstructible&&) = default;
350 template <class Derived, bool, bool Noexcept>
351 struct CopyAssignable {
352 constexpr CopyAssignable() = default;
353 constexpr CopyAssignable(const CopyAssignable&) = default;
354 constexpr CopyAssignable(CopyAssignable&&) = default;
355 CopyAssignable& operator=(const CopyAssignable& that) noexcept(Noexcept) {
356 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
359 CopyAssignable& operator=(CopyAssignable&&) = default;
362 template <class Derived, bool Noexcept>
363 struct CopyAssignable<Derived, false, Noexcept> {
364 constexpr CopyAssignable() = default;
365 constexpr CopyAssignable(const CopyAssignable&) = default;
366 constexpr CopyAssignable(CopyAssignable&&) = default;
367 CopyAssignable& operator=(const CopyAssignable&) = delete;
368 CopyAssignable& operator=(CopyAssignable&&) = default;
371 template <class Derived, bool, bool Noexcept>
372 struct MoveAssignable {
373 constexpr MoveAssignable() = default;
374 constexpr MoveAssignable(const MoveAssignable&) = default;
375 constexpr MoveAssignable(MoveAssignable&&) = default;
376 MoveAssignable& operator=(const MoveAssignable&) = default;
377 MoveAssignable& operator=(MoveAssignable&& that) noexcept(Noexcept) {
378 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
383 template <class Derived, bool Noexcept>
384 struct MoveAssignable<Derived, false, Noexcept> {
385 constexpr MoveAssignable() = default;
386 constexpr MoveAssignable(const MoveAssignable&) = default;
387 constexpr MoveAssignable(MoveAssignable&&) = default;
388 MoveAssignable& operator=(const MoveAssignable&) = default;
389 MoveAssignable& operator=(MoveAssignable&& that) = delete;
392 template <class Value, class Error>
393 struct ExpectedStorage<Value, Error, StorageType::eUnion>
394 : ExpectedUnion<Value, Error>,
396 ExpectedStorage<Value, Error, StorageType::eUnion>,
397 StrictAllOf<std::is_copy_constructible, Value, Error>::value,
398 StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::value>,
400 ExpectedStorage<Value, Error, StorageType::eUnion>,
401 StrictAllOf<std::is_move_constructible, Value, Error>::value,
402 StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::value>,
404 ExpectedStorage<Value, Error, StorageType::eUnion>,
405 StrictAllOf<IsCopyable, Value, Error>::value,
406 StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
408 ExpectedStorage<Value, Error, StorageType::eUnion>,
409 StrictAllOf<IsMovable, Value, Error>::value,
410 StrictAllOf<IsNothrowMovable, Value, Error>::value> {
411 using value_type = Value;
412 using error_type = Error;
413 using Base = ExpectedUnion<Value, Error>;
414 template <class E = Error, class = decltype(E{})>
415 constexpr ExpectedStorage() noexcept(noexcept(E{})) : Base{ErrorTag{}} {}
416 ExpectedStorage(const ExpectedStorage&) = default;
417 ExpectedStorage(ExpectedStorage&&) = default;
418 ExpectedStorage& operator=(const ExpectedStorage&) = default;
419 ExpectedStorage& operator=(ExpectedStorage&&) = default;
420 using ExpectedUnion<Value, Error>::ExpectedUnion;
424 void clear() noexcept {
425 switch (this->which_) {
427 this->value().~Value();
430 this->error().~Error();
435 this->which_ = Which::eEmpty;
437 bool uninitializedByException() const noexcept {
438 return this->which_ == Which::eEmpty;
440 template <class... Vs>
441 void assignValue(Vs&&... vs) {
442 if (this->which_ == Which::eValue) {
443 expected_detail::doEmplaceAssign(
444 0, this->value(), static_cast<Vs&&>(vs)...);
447 ::new ((void*)std::addressof(this->value()))
448 Value(static_cast<Vs&&>(vs)...);
449 this->which_ = Which::eValue;
452 template <class... Es>
453 void assignError(Es&&... es) {
454 if (this->which_ == Which::eError) {
455 expected_detail::doEmplaceAssign(
456 0, this->error(), static_cast<Es&&>(es)...);
459 ::new ((void*)std::addressof(this->error()))
460 Error(static_cast<Es&&>(es)...);
461 this->which_ = Which::eError;
464 bool isSelfAssign(const ExpectedStorage* that) const {
467 constexpr bool isSelfAssign(const void*) const {
470 template <class Other>
471 void assign(Other&& that) {
472 if (isSelfAssign(&that)) {
475 switch (that.which_) {
477 this->assignValue(static_cast<Other&&>(that).value());
480 this->assignError(static_cast<Other&&>(that).error());
489 // For small (pointer-sized) trivial types, a struct is faster than a union.
490 template <class Value, class Error>
491 struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
492 using value_type = Value;
493 using error_type = Error;
498 constexpr ExpectedStorage() noexcept
499 : which_(Which::eError), error_{}, value_{} {}
500 explicit constexpr ExpectedStorage(EmptyTag) noexcept
501 : which_(Which::eEmpty), error_{}, value_{} {}
502 template <class... Vs>
503 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
504 noexcept(Value(static_cast<Vs&&>(vs)...)))
505 : which_(Which::eValue), error_{}, value_(static_cast<Vs&&>(vs)...) {}
506 template <class... Es>
507 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
508 noexcept(Error(static_cast<Es&&>(es)...)))
509 : which_(Which::eError), error_(static_cast<Es&&>(es)...), value_{} {}
510 void clear() noexcept {}
511 constexpr static bool uninitializedByException() noexcept {
514 template <class... Vs>
515 void assignValue(Vs&&... vs) {
516 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
517 which_ = Which::eValue;
519 template <class... Es>
520 void assignError(Es&&... es) {
521 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
522 which_ = Which::eError;
524 template <class Other>
525 void assign(Other&& that) {
526 switch (that.which_) {
528 this->assignValue(static_cast<Other&&>(that).value());
531 this->assignError(static_cast<Other&&>(that).error());
541 const Value& value() const& {
545 return std::move(value_);
547 // TODO (t17322426): remove when VS2015 support is deprecated
548 // VS2015 static analyzer incorrectly flags these as unreachable in certain
549 // circumstances. VS2017 does not have this problem on the same code.
551 FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
555 const Error& error() const& {
559 return std::move(error_);
564 namespace expected_detail_ExpectedHelper {
565 // Tricky hack so that Expected::then can handle lambdas that return void
567 inline T&& operator,(T&& t, Unit) noexcept {
568 return static_cast<T&&>(t);
571 struct ExpectedHelper {
572 template <class Error, class T>
573 static constexpr Expected<T, Error> return_(T t) {
574 return folly::makeExpected<Error>(t);
579 class U FOLLY_REQUIRES_TRAILING(
580 expected_detail::IsConvertible<U&&, Error>::value)>
581 static constexpr Expected<T, Error> return_(Expected<T, U> t) {
585 template <class This>
586 static typename std::decay<This>::type then_(This&& ex) {
587 return static_cast<This&&>(ex);
591 // Don't warn about not using the overloaded comma operator.
592 FOLLY_MSVC_DISABLE_WARNING(4913)
597 class E = ExpectedErrorType<This>,
598 class T = ExpectedHelper>
599 static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
600 T::template return_<E>(
601 (std::declval<Fn>()(std::declval<This>().value()), unit)),
602 std::declval<Fns>()...)) {
603 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
605 T::template return_<E>(
606 // Uses the comma operator defined above IFF the lambda
608 (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
609 static_cast<Fns&&>(fns)...);
611 return makeUnexpected(static_cast<This&&>(ex).error());
618 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
619 class Err = decltype(std::declval<No>()(std::declval<This>().error()))
620 FOLLY_REQUIRES_TRAILING(!std::is_void<Err>::value)>
621 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
622 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
623 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
625 throw static_cast<No&&>(no)(static_cast<This&&>(ex).error());
632 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
633 class Err = decltype(std::declval<No>()(std::declval<This&>().error()))
634 FOLLY_REQUIRES_TRAILING(std::is_void<Err>::value)>
635 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
636 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
637 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
639 static_cast<No&&>(no)(ex.error());
640 throw typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess()(
641 static_cast<This&&>(ex).error());
645 } // namespace expected_detail_ExpectedHelper
646 /* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
648 struct UnexpectedTag {};
650 } // namespace expected_detail
653 expected_detail::UnexpectedTag (&)(expected_detail::UnexpectedTag);
655 inline expected_detail::UnexpectedTag unexpected(
656 expected_detail::UnexpectedTag = {}) {
661 * An exception type thrown by Expected on catastrophic logic errors.
663 class BadExpectedAccess : public std::logic_error {
665 BadExpectedAccess() : std::logic_error("bad Expected access") {}
668 namespace expected_detail {
670 [[noreturn]] void throwBadExpectedAccess();
672 } // namespace expected_detail
675 * Unexpected - a helper type used to disambiguate the construction of
676 * Expected objects in the error state.
678 template <class Error>
679 class Unexpected final : ColdClass {
681 friend class Unexpected;
682 template <class V, class E>
683 friend class Expected;
684 friend struct expected_detail::ExpectedHelper;
688 * Unexpected::BadExpectedAccess - An exception type thrown by Expected
689 * when the user tries to access the nested value but the Expected object is
690 * actually storing an error code.
692 class BadExpectedAccess : public folly::BadExpectedAccess {
694 explicit BadExpectedAccess(Error err)
695 : folly::BadExpectedAccess{}, error_(std::move(err)) {}
697 * The error code that was held by the Expected object when the user
698 * erroneously requested the value.
700 Error error() const {
711 Unexpected() = default;
712 Unexpected(const Unexpected&) = default;
713 Unexpected(Unexpected&&) = default;
714 Unexpected& operator=(const Unexpected&) = default;
715 Unexpected& operator=(Unexpected&&) = default;
716 constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {}
717 constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {}
719 template <class Other FOLLY_REQUIRES_TRAILING(
720 std::is_constructible<Error, Other&&>::value)>
721 constexpr /* implicit */ Unexpected(Unexpected<Other> that)
722 : error_(std::move(that.error())) {}
727 template <class Other FOLLY_REQUIRES_TRAILING(
728 std::is_assignable<Error&, Other&&>::value)>
729 Unexpected& operator=(Unexpected<Other> that) {
730 error_ = std::move(that.error());
739 const Error& error() const& {
743 return std::move(error_);
747 struct MakeBadExpectedAccess {
749 BadExpectedAccess operator()(E&& err) const {
750 return BadExpectedAccess(static_cast<E&&>(err));
758 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
759 inline bool operator==(
760 const Unexpected<Error>& lhs,
761 const Unexpected<Error>& rhs) {
762 return lhs.error() == rhs.error();
766 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
767 inline bool operator!=(
768 const Unexpected<Error>& lhs,
769 const Unexpected<Error>& rhs) {
770 return !(lhs == rhs);
774 * For constructing an Unexpected object from an error code. Unexpected objects
775 * are implicitly convertible to Expected object in the error state. Usage is
778 * enum class MyErrorCode { BAD_ERROR, WORSE_ERROR };
779 * Expected<int, MyErrorCode> myAPI() {
781 * return i ? makeExpected<MyErrorCode>(i)
782 * : makeUnexpected(MyErrorCode::BAD_ERROR);
785 template <class Error>
786 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(
788 return Unexpected<typename std::decay<Error>::type>{
789 static_cast<Error&&>(err)};
793 * Expected - For holding a value or an error. Useful as an alternative to
794 * exceptions, for APIs where throwing on failure would be too expensive.
796 * Expected<Value, Error> is a variant over the types Value and Error.
798 * Expected does not offer support for references. Use
799 * Expected<std::reference_wrapper<T>, Error> if your API needs to return a
800 * reference or an error.
802 * Expected offers a continuation-based interface to reduce the boilerplate
803 * of checking error codes. The Expected::then member function takes a lambda
804 * that is to execute should the Expected object contain a value. The return
805 * value of the lambda is wrapped in an Expected and returned. If the lambda is
806 * not executed because the Expected contains an error, the error is returned
807 * immediately in a new Expected object.
809 * Expected<int, Error> funcTheFirst();
810 * Expected<std::string, Error> funcTheSecond() {
811 * return funcTheFirst().then([](int i) { return std::to_string(i); });
814 * The above line of code could more verbosely written as:
816 * Expected<std::string, Error> funcTheSecond() {
817 * if (auto ex = funcTheFirst()) {
818 * return std::to_string(*ex);
820 * return makeUnexpected(ex.error());
823 * Continuations can chain, like:
825 * Expected<D, Error> maybeD = someFunc()
826 * .then([](A a){return B(a);})
827 * .then([](B b){return C(b);})
828 * .then([](C c){return D(c);});
830 * To avoid the redundant error checking that would happen if a call at the
831 * front of the chain returns an error, these call chains can be collaped into
832 * a single call to .then:
834 * Expected<D, Error> maybeD = someFunc()
835 * .then([](A a){return B(a);},
836 * [](B b){return C(b);},
837 * [](C c){return D(c);});
839 * The result of .then() is wrapped into Expected< ~, Error > if it isn't
840 * of that form already. Consider the following code:
842 * extern Expected<std::string, Error> readLineFromIO();
843 * extern Expected<int, Error> parseInt(std::string);
844 * extern int increment(int);
846 * Expected<int, Error> x = readLineFromIO().then(parseInt).then(increment);
848 * From the code above, we see that .then() works both with functions that
849 * return an Expected< ~, Error > (like parseInt) and with ones that return
850 * a plain value (like increment). In the case of parseInt, .then() returns
851 * the result of parseInt as-is. In the case of increment, it wraps the int
852 * that increment returns into an Expected< int, Error >.
854 * Sometimes when using a continuation you would prefer an exception to be
855 * thrown for a value-less Expected. For that you can use .thenOrThrow, as
859 * .thenOrThrow([](A a){return B(a);});
861 * The above call to thenOrThrow will invoke the lambda if the Expected returned
862 * by someFunc() contains a value. Otherwise, it will throw an exception of type
863 * Unexpected<Error>::BadExpectedAccess. If you prefer it throw an exception of
864 * a different type, you can pass a second lambda to thenOrThrow:
867 * .thenOrThrow([](A a){return B(a);},
868 * [](Error e) {throw MyException(e);});
870 * Like C++17's std::variant, Expected offers the almost-never-empty guarantee;
871 * that is, an Expected<Value, Error> almost always contains either a Value or
872 * and Error. Partially-formed Expected objects occur when an assignment to
873 * an Expected object that would change the type of the contained object (Value-
874 * to-Error or vice versa) throws. Trying to access either the contained value
875 * or error object causes Expected to throw folly::BadExpectedAccess.
877 * Expected models OptionalPointee, so calling 'get_pointer(ex)' will return a
878 * pointer to nullptr if the 'ex' is in the error state, and a pointer to the
881 * Expected<int, Error> maybeInt = ...;
882 * if (int* v = get_pointer(maybeInt)) {
883 * cout << *v << endl;
886 template <class Value, class Error>
887 class Expected final : expected_detail::ExpectedStorage<Value, Error> {
888 template <class, class>
889 friend class Expected;
890 template <class, class, expected_detail::StorageType>
891 friend struct expected_detail::ExpectedStorage;
892 friend struct expected_detail::ExpectedHelper;
893 using Base = expected_detail::ExpectedStorage<Value, Error>;
894 using MakeBadExpectedAccess =
895 typename Unexpected<Error>::MakeBadExpectedAccess;
899 const Base& base() const& {
903 return std::move(*this);
907 using value_type = Value;
908 using error_type = Error;
909 using IsTriviallyCopyable = typename expected_detail::
910 StrictAllOf<IsTriviallyCopyable, Value, Error>::type;
913 using rebind = Expected<U, Error>;
916 !std::is_reference<Value>::value,
917 "Expected may not be used with reference types");
919 !std::is_abstract<Value>::value,
920 "Expected may not be used with abstract types");
925 template <class B = Base, class = decltype(B{})>
926 Expected() noexcept(noexcept(B{})) : Base{} {}
927 Expected(const Expected& that) = default;
928 Expected(Expected&& that) = default;
932 class E FOLLY_REQUIRES_TRAILING(
933 !std::is_same<Expected<V, E>, Expected>::value &&
934 std::is_constructible<Value, V&&>::value &&
935 std::is_constructible<Error, E&&>::value)>
936 Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} {
937 *this = std::move(that);
940 FOLLY_REQUIRES(std::is_copy_constructible<Value>::value)
941 constexpr /* implicit */ Expected(const Value& val) noexcept(
942 noexcept(Value(val)))
943 : Base{expected_detail::ValueTag{}, val} {}
945 FOLLY_REQUIRES(std::is_move_constructible<Value>::value)
946 constexpr /* implicit */ Expected(Value&& val) noexcept(
947 noexcept(Value(std::move(val))))
948 : Base{expected_detail::ValueTag{}, std::move(val)} {}
950 template <class T FOLLY_REQUIRES_TRAILING(
951 std::is_convertible<T, Value>::value &&
952 !std::is_convertible<T, Error>::value)>
953 constexpr /* implicit */ Expected(T&& val) noexcept(
954 noexcept(Value(static_cast<T&&>(val))))
955 : Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {}
957 template <class... Ts FOLLY_REQUIRES_TRAILING(
958 std::is_constructible<Value, Ts&&...>::value)>
959 explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
960 noexcept(Value(std::declval<Ts>()...)))
961 : Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {}
965 class... Ts FOLLY_REQUIRES_TRAILING(
966 std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
968 explicit constexpr Expected(
970 std::initializer_list<U> il,
971 Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
972 : Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {}
974 // If overload resolution selects one of these deleted functions, that
975 // means you need to use makeUnexpected
976 /* implicit */ Expected(const Error&) = delete;
977 /* implicit */ Expected(Error&&) = delete;
979 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
980 constexpr Expected(unexpected_t, const Error& err) noexcept(
981 noexcept(Error(err)))
982 : Base{expected_detail::ErrorTag{}, err} {}
984 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
985 constexpr Expected(unexpected_t, Error&& err) noexcept(
986 noexcept(Error(std::move(err))))
987 : Base{expected_detail::ErrorTag{}, std::move(err)} {}
989 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
990 constexpr /* implicit */ Expected(const Unexpected<Error>& err) noexcept(
991 noexcept(Error(err.error())))
992 : Base{expected_detail::ErrorTag{}, err.error()} {}
994 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
995 constexpr /* implicit */ Expected(Unexpected<Error>&& err) noexcept(
996 noexcept(Error(std::move(err.error()))))
997 : Base{expected_detail::ErrorTag{}, std::move(err.error())} {}
1000 * Assignment operators
1002 Expected& operator=(const Expected& that) = default;
1003 Expected& operator=(Expected&& that) = default;
1007 class E FOLLY_REQUIRES_TRAILING(
1008 !std::is_same<Expected<V, E>, Expected>::value &&
1009 expected_detail::IsConvertible<V&&, Value>::value &&
1010 expected_detail::IsConvertible<E&&, Error>::value)>
1011 Expected& operator=(Expected<V, E> that) {
1012 this->assign(std::move(that));
1016 FOLLY_REQUIRES(expected_detail::IsCopyable<Value>::value)
1017 Expected& operator=(const Value& val) noexcept(
1018 expected_detail::IsNothrowCopyable<Value>::value) {
1019 this->assignValue(val);
1023 FOLLY_REQUIRES(expected_detail::IsMovable<Value>::value)
1024 Expected& operator=(Value&& val) noexcept(
1025 expected_detail::IsNothrowMovable<Value>::value) {
1026 this->assignValue(std::move(val));
1030 template <class T FOLLY_REQUIRES_TRAILING(
1031 std::is_convertible<T, Value>::value &&
1032 !std::is_convertible<T, Error>::value)>
1033 Expected& operator=(T&& val) {
1034 this->assignValue(static_cast<T&&>(val));
1038 FOLLY_REQUIRES(expected_detail::IsCopyable<Error>::value)
1039 Expected& operator=(const Unexpected<Error>& err) noexcept(
1040 expected_detail::IsNothrowCopyable<Error>::value) {
1041 this->assignError(err.error());
1045 FOLLY_REQUIRES(expected_detail::IsMovable<Error>::value)
1046 Expected& operator=(Unexpected<Error>&& err) noexcept(
1047 expected_detail::IsNothrowMovable<Error>::value) {
1048 this->assignError(std::move(err.error()));
1052 // Used only when an Expected is used with coroutines on MSVC
1053 /* implicit */ Expected(const expected_detail::PromiseReturn<Value, Error>& p)
1055 p.promise_->value_ = this;
1058 template <class... Ts FOLLY_REQUIRES_TRAILING(
1059 std::is_constructible<Value, Ts&&...>::value)>
1060 void emplace(Ts&&... ts) {
1061 this->assignValue(static_cast<Ts&&>(ts)...);
1067 void swap(Expected& that) noexcept(
1068 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1069 if (this->uninitializedByException() || that.uninitializedByException()) {
1070 expected_detail::throwBadExpectedAccess();
1075 swap(this->value_, that.value_);
1077 Error e(std::move(that.error_));
1078 that.assignValue(std::move(this->value_));
1079 this->assignError(std::move(e));
1083 swap(this->error_, that.error_);
1085 Error e(std::move(this->error_));
1086 this->assignValue(std::move(that.value_));
1087 that.assignError(std::move(e));
1092 // If overload resolution selects one of these deleted functions, that
1093 // means you need to use makeUnexpected
1094 /* implicit */ Expected& operator=(const Error&) = delete;
1095 /* implicit */ Expected& operator=(Error&&) = delete;
1098 * Relational Operators
1100 template <class Val, class Err>
1101 friend typename std::enable_if<IsEqualityComparable<Val>::value, bool>::type
1102 operator==(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1103 template <class Val, class Err>
1104 friend typename std::enable_if<IsLessThanComparable<Val>::value, bool>::type
1105 operator<(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1110 constexpr bool hasValue() const noexcept {
1111 return LIKELY(expected_detail::Which::eValue == this->which_);
1114 constexpr bool hasError() const noexcept {
1115 return UNLIKELY(expected_detail::Which::eError == this->which_);
1118 using Base::uninitializedByException;
1120 const Value& value() const& {
1122 return this->Base::value();
1127 return this->Base::value();
1130 Value&& value() && {
1132 return std::move(this->Base::value());
1135 const Error& error() const& {
1137 return this->Base::error();
1142 return this->Base::error();
1145 Error&& error() && {
1147 return std::move(this->Base::error());
1150 // Return a copy of the value if set, or a given default if not.
1152 Value value_or(U&& dflt) const& {
1153 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1154 return this->value_;
1156 return static_cast<U&&>(dflt);
1160 Value value_or(U&& dflt) && {
1161 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1162 return std::move(this->value_);
1164 return static_cast<U&&>(dflt);
1167 explicit constexpr operator bool() const noexcept {
1171 const Value& operator*() const& {
1172 return this->value();
1175 Value& operator*() & {
1176 return this->value();
1179 Value&& operator*() && {
1180 return std::move(this->value());
1183 const Value* operator->() const {
1184 return std::addressof(this->value());
1187 Value* operator->() {
1188 return std::addressof(this->value());
1191 const Value* get_pointer() const& noexcept {
1192 return hasValue() ? std::addressof(this->value_) : nullptr;
1195 Value* get_pointer() & noexcept {
1196 return hasValue() ? std::addressof(this->value_) : nullptr;
1199 Value* get_pointer() && = delete;
1204 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1205 auto then(Fns&&... fns) const& -> decltype(
1206 expected_detail::ExpectedHelper::then_(
1207 std::declval<const Base&>(),
1208 std::declval<Fns>()...)) {
1209 if (this->uninitializedByException()) {
1210 expected_detail::throwBadExpectedAccess();
1212 return expected_detail::ExpectedHelper::then_(
1213 base(), static_cast<Fns&&>(fns)...);
1216 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1217 auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1218 std::declval<Base&>(),
1219 std::declval<Fns>()...)) {
1220 if (this->uninitializedByException()) {
1221 expected_detail::throwBadExpectedAccess();
1223 return expected_detail::ExpectedHelper::then_(
1224 base(), static_cast<Fns&&>(fns)...);
1227 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1228 auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1229 std::declval<Base&&>(),
1230 std::declval<Fns>()...)) {
1231 if (this->uninitializedByException()) {
1232 expected_detail::throwBadExpectedAccess();
1234 return expected_detail::ExpectedHelper::then_(
1235 std::move(base()), static_cast<Fns&&>(fns)...);
1241 template <class Yes, class No = MakeBadExpectedAccess>
1242 auto thenOrThrow(Yes&& yes, No&& no = No{}) const& -> decltype(
1243 std::declval<Yes>()(std::declval<const Value&>())) {
1244 using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1245 if (this->uninitializedByException()) {
1246 expected_detail::throwBadExpectedAccess();
1248 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1249 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1252 template <class Yes, class No = MakeBadExpectedAccess>
1253 auto thenOrThrow(Yes&& yes, No&& no = No{}) & -> decltype(
1254 std::declval<Yes>()(std::declval<Value&>())) {
1255 using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1256 if (this->uninitializedByException()) {
1257 expected_detail::throwBadExpectedAccess();
1259 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1260 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1263 template <class Yes, class No = MakeBadExpectedAccess>
1264 auto thenOrThrow(Yes&& yes, No&& no = No{}) && -> decltype(
1265 std::declval<Yes>()(std::declval<Value&&>())) {
1266 using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1267 if (this->uninitializedByException()) {
1268 expected_detail::throwBadExpectedAccess();
1270 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1271 std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1275 void requireValue() const {
1276 if (UNLIKELY(!hasValue())) {
1277 if (LIKELY(hasError())) {
1278 throw typename Unexpected<Error>::BadExpectedAccess(this->error_);
1280 expected_detail::throwBadExpectedAccess();
1284 void requireError() const {
1285 if (UNLIKELY(!hasError())) {
1286 expected_detail::throwBadExpectedAccess();
1290 expected_detail::Which which() const noexcept {
1291 return this->which_;
1295 template <class Value, class Error>
1296 inline typename std::enable_if<IsEqualityComparable<Value>::value, bool>::type
1298 const Expected<Value, Error>& lhs,
1299 const Expected<Value, Error>& rhs) {
1300 if (UNLIKELY(lhs.uninitializedByException())) {
1301 expected_detail::throwBadExpectedAccess();
1303 if (UNLIKELY(lhs.which_ != rhs.which_)) {
1306 if (UNLIKELY(lhs.hasError())) {
1307 return true; // All error states are considered equal
1309 return lhs.value_ == rhs.value_;
1314 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Value>::value)>
1315 inline bool operator!=(
1316 const Expected<Value, Error>& lhs,
1317 const Expected<Value, Error>& rhs) {
1318 return !(rhs == lhs);
1321 template <class Value, class Error>
1322 inline typename std::enable_if<IsLessThanComparable<Value>::value, bool>::type
1324 const Expected<Value, Error>& lhs,
1325 const Expected<Value, Error>& rhs) {
1327 lhs.uninitializedByException() || rhs.uninitializedByException())) {
1328 expected_detail::throwBadExpectedAccess();
1330 if (UNLIKELY(lhs.hasError())) {
1331 return !rhs.hasError();
1333 if (UNLIKELY(rhs.hasError())) {
1336 return lhs.value_ < rhs.value_;
1341 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1342 inline bool operator<=(
1343 const Expected<Value, Error>& lhs,
1344 const Expected<Value, Error>& rhs) {
1345 return !(rhs < lhs);
1350 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1351 inline bool operator>(
1352 const Expected<Value, Error>& lhs,
1353 const Expected<Value, Error>& rhs) {
1359 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1360 inline bool operator>=(
1361 const Expected<Value, Error>& lhs,
1362 const Expected<Value, Error>& rhs) {
1363 return !(lhs < rhs);
1367 * swap Expected values
1369 template <class Error, class Value>
1370 void swap(Expected<Error, Value>& lhs, Expected<Value, Error>& rhs) noexcept(
1371 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1375 template <class Value, class Error>
1376 const Value* get_pointer(const Expected<Value, Error>& ex) noexcept {
1377 return ex.get_pointer();
1380 template <class Value, class Error>
1381 Value* get_pointer(Expected<Value, Error>& ex) noexcept {
1382 return ex.get_pointer();
1386 * For constructing an Expected object from a value, with the specified
1387 * Error type. Usage is as follows:
1389 * enum MyErrorCode { BAD_ERROR, WORSE_ERROR };
1390 * Expected<int, MyErrorCode> myAPI() {
1392 * return i ? makeExpected<MyErrorCode>(i) : makeUnexpected(BAD_ERROR);
1395 template <class Error, class Value>
1396 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
1398 return Expected<typename std::decay<Value>::type, Error>{
1399 in_place, static_cast<Value&&>(val)};
1402 // Suppress comparability of Optional<T> with T, despite implicit conversion.
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 Expected<Value, Error>&, const Value& other) = 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 template <class Value, class Error>
1426 bool operator>(const Value& other, const Expected<Value, Error>&) = delete;
1428 } // namespace folly
1430 #if defined(__GNUC__) && !defined(__clang__)
1431 #pragma GCC diagnostic pop
1434 #undef FOLLY_REQUIRES
1435 #undef FOLLY_REQUIRES_TRAILING
1437 // Enable the use of folly::Expected with `co_await`
1438 // Inspired by https://github.com/toby-allsopp/coroutine_monad
1439 #if FOLLY_HAS_COROUTINES
1440 #include <experimental/coroutine>
1443 namespace expected_detail {
1444 template <typename Value, typename Error>
1447 template <typename Value, typename Error>
1448 struct PromiseReturn {
1449 Optional<Expected<Value, Error>> storage_;
1450 Promise<Value, Error>* promise_;
1451 /* implicit */ PromiseReturn(Promise<Value, Error>& promise) noexcept
1452 : promise_(&promise) {
1453 promise_->value_ = &storage_;
1455 PromiseReturn(PromiseReturn&& that) noexcept
1456 : PromiseReturn{*that.promise_} {}
1458 /* implicit */ operator Expected<Value, Error>() & {
1459 return std::move(*storage_);
1463 template <typename Value, typename Error>
1465 Optional<Expected<Value, Error>>* value_ = nullptr;
1466 Promise() = default;
1467 Promise(Promise const&) = delete;
1468 // This should work regardless of whether the compiler generates:
1469 // folly::Expected<Value, Error> retobj{ p.get_return_object(); } // MSVC
1471 // auto retobj = p.get_return_object(); // clang
1472 PromiseReturn<Value, Error> get_return_object() noexcept {
1475 std::experimental::suspend_never initial_suspend() const noexcept {
1478 std::experimental::suspend_never final_suspend() const {
1481 template <typename U>
1482 void return_value(U&& u) {
1483 value_->emplace(static_cast<U&&>(u));
1485 void unhandled_exception() {
1486 // Technically, throwing from unhandled_exception is underspecified:
1487 // https://github.com/GorNishanov/CoroutineWording/issues/17
1492 template <typename Value, typename Error>
1494 Expected<Value, Error> o_;
1496 explicit Awaitable(Expected<Value, Error> o) : o_(std::move(o)) {}
1498 bool await_ready() const noexcept {
1499 return o_.hasValue();
1501 Value await_resume() {
1502 return std::move(o_.value());
1505 // Explicitly only allow suspension into a Promise
1506 template <typename U>
1507 void await_suspend(std::experimental::coroutine_handle<Promise<U, Error>> h) {
1508 *h.promise().value_ = makeUnexpected(std::move(o_.error()));
1509 // Abort the rest of the coroutine. resume() is not going to be called
1513 } // namespace expected_detail
1515 template <typename Value, typename Error>
1516 expected_detail::Awaitable<Value, Error>
1517 /* implicit */ operator co_await(Expected<Value, Error> o) {
1518 return expected_detail::Awaitable<Value, Error>{std::move(o)};
1520 } // namespace folly
1522 // This makes folly::Expected<Value> useable as a coroutine return type...
1524 namespace experimental {
1525 template <typename Value, typename Error, typename... Args>
1526 struct coroutine_traits<folly::Expected<Value, Error>, Args...> {
1527 using promise_type = folly::expected_detail::Promise<Value, Error>;
1529 } // namespace experimental
1531 #endif // FOLLY_HAS_COROUTINES