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/Likely.h>
35 #include <folly/Optional.h>
36 #include <folly/Portability.h>
37 #include <folly/Preprocessor.h>
38 #include <folly/Traits.h>
39 #include <folly/Unit.h>
40 #include <folly/Utility.h>
42 #define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__)
44 #define FOLLY_REQUIRES_IMPL(...) \
45 bool FOLLY_EXPECTED_ID(Requires) = false, \
46 typename std::enable_if< \
47 (FOLLY_EXPECTED_ID(Requires) || static_cast<bool>(__VA_ARGS__)), \
50 #define FOLLY_REQUIRES_TRAILING(...) , FOLLY_REQUIRES_IMPL(__VA_ARGS__)
52 #define FOLLY_REQUIRES(...) template <FOLLY_REQUIRES_IMPL(__VA_ARGS__)>
55 * gcc-4.7 warns about use of uninitialized memory around the use of storage_
56 * even though this is explicitly initialized at each point.
58 #if defined(__GNUC__) && !defined(__clang__)
59 #pragma GCC diagnostic push
60 #pragma GCC diagnostic ignored "-Wuninitialized"
61 #pragma GCC diagnostic ignored "-Wpragmas"
62 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
68 * Forward declarations
70 template <class Error>
73 template <class Error>
74 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(Error&&);
76 template <class Value, class Error>
79 template <class Error, class Value>
80 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
84 * Alias for an Expected type's assiciated value_type
86 template <class Expected>
87 using ExpectedValueType =
88 typename std::remove_reference<Expected>::type::value_type;
91 * Alias for an Expected type's assiciated error_type
93 template <class Expected>
94 using ExpectedErrorType =
95 typename std::remove_reference<Expected>::type::error_type;
98 namespace expected_detail {
100 template <typename Value, typename Error>
101 struct PromiseReturn;
104 // MSVC 2015 can't handle the StrictConjunction, so we have
105 // to use std::conjunction instead.
106 template <template <class...> class Trait, class... Ts>
107 using StrictAllOf = std::conjunction<Trait<Ts>...>;
109 template <template <class...> class Trait, class... Ts>
110 using StrictAllOf = StrictConjunction<Trait<Ts>...>;
114 using IsCopyable = StrictConjunction<
115 std::is_copy_constructible<T>,
116 std::is_copy_assignable<T>>;
119 using IsMovable = StrictConjunction<
120 std::is_move_constructible<T>,
121 std::is_move_assignable<T>>;
124 using IsNothrowCopyable = StrictConjunction<
125 std::is_nothrow_copy_constructible<T>,
126 std::is_nothrow_copy_assignable<T>>;
129 using IsNothrowMovable = StrictConjunction<
130 std::is_nothrow_move_constructible<T>,
131 std::is_nothrow_move_assignable<T>>;
133 template <class From, class To>
134 using IsConvertible = StrictConjunction<
135 std::is_constructible<To, From>,
136 std::is_assignable<To&, From>>;
138 template <class T, class U>
139 auto doEmplaceAssign(int, T& t, U&& u) -> decltype(void(t = (U &&)u)) {
143 template <class T, class U>
144 auto doEmplaceAssign(long, T& t, U&& u) -> decltype(void(T((U &&)u))) {
146 ::new ((void*)std::addressof(t)) T((U &&)u);
149 template <class T, class... Us>
150 auto doEmplaceAssign(int, T& t, Us&&... us)
151 -> decltype(void(t = T((Us &&)us...))) {
155 template <class T, class... Us>
156 auto doEmplaceAssign(long, T& t, Us&&... us)
157 -> decltype(void(T((Us &&)us...))) {
159 ::new ((void*)std::addressof(t)) T((Us &&)us...);
165 enum class Which : unsigned char { eEmpty, eValue, eError };
166 enum class StorageType { ePODStruct, ePODUnion, eUnion };
168 template <class Value, class Error>
169 constexpr StorageType getStorageType() {
170 return StrictAllOf<IsTriviallyCopyable, Value, Error>::value
171 ? (sizeof(std::pair<Value, Error>) <= sizeof(void * [2]) &&
172 StrictAllOf<std::is_trivial, Value, Error>::value
173 ? StorageType::ePODStruct
174 : StorageType::ePODUnion)
175 : StorageType::eUnion;
181 StorageType = expected_detail::getStorageType<Value, Error>()> // ePODUnion
182 struct ExpectedStorage {
183 using value_type = Value;
184 using error_type = Error;
192 template <class E = Error, class = decltype(E{})>
193 constexpr ExpectedStorage() noexcept(noexcept(E{}))
194 : error_{}, which_(Which::eError) {}
195 explicit constexpr ExpectedStorage(EmptyTag) noexcept
196 : ch_{}, which_(Which::eEmpty) {}
197 template <class... Vs>
198 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
199 noexcept(Value(static_cast<Vs&&>(vs)...)))
200 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
201 template <class... Es>
202 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
203 noexcept(Error(static_cast<Es&&>(es)...)))
204 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
205 void clear() noexcept {}
206 static constexpr bool uninitializedByException() noexcept {
207 // Although which_ may temporarily be eEmpty during construction, it
208 // is always either eValue or eError for a fully-constructed Expected.
211 template <class... Vs>
212 void assignValue(Vs&&... vs) {
213 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
214 which_ = Which::eValue;
216 template <class... Es>
217 void assignError(Es&&... es) {
218 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
219 which_ = Which::eError;
221 template <class Other>
222 void assign(Other&& that) {
223 switch (that.which_) {
225 this->assignValue(static_cast<Other&&>(that).value());
228 this->assignError(static_cast<Other&&>(that).error());
238 const Value& value() const& {
242 return std::move(value_);
244 // TODO (t17322426): remove when VS2015 support is deprecated
245 // VS2015 static analyzer incorrectly flags these as unreachable in certain
246 // circumstances. VS2017 does not have this problem on the same code.
248 FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
252 const Error& error() const& {
256 return std::move(error_);
261 template <class Value, class Error>
262 struct ExpectedUnion {
268 Which which_ = Which::eEmpty;
270 explicit constexpr ExpectedUnion(EmptyTag) noexcept {}
271 template <class... Vs>
272 explicit constexpr ExpectedUnion(ValueTag, Vs&&... vs) noexcept(
273 noexcept(Value(static_cast<Vs&&>(vs)...)))
274 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
275 template <class... Es>
276 explicit constexpr ExpectedUnion(ErrorTag, Es&&... es) noexcept(
277 noexcept(Error(static_cast<Es&&>(es)...)))
278 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
279 ExpectedUnion(const ExpectedUnion&) {}
280 ExpectedUnion(ExpectedUnion&&) noexcept {}
281 ExpectedUnion& operator=(const ExpectedUnion&) {
284 ExpectedUnion& operator=(ExpectedUnion&&) noexcept {
291 const Value& value() const& {
295 return std::move(value_);
300 const Error& error() const& {
304 return std::move(error_);
308 template <class Derived, bool, bool Noexcept>
309 struct CopyConstructible {
310 constexpr CopyConstructible() = default;
311 CopyConstructible(const CopyConstructible& that) noexcept(Noexcept) {
312 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
314 constexpr CopyConstructible(CopyConstructible&&) = default;
315 CopyConstructible& operator=(const CopyConstructible&) = default;
316 CopyConstructible& operator=(CopyConstructible&&) = default;
319 template <class Derived, bool Noexcept>
320 struct CopyConstructible<Derived, false, Noexcept> {
321 constexpr CopyConstructible() = default;
322 CopyConstructible(const CopyConstructible&) = delete;
323 constexpr CopyConstructible(CopyConstructible&&) = default;
324 CopyConstructible& operator=(const CopyConstructible&) = default;
325 CopyConstructible& operator=(CopyConstructible&&) = default;
328 template <class Derived, bool, bool Noexcept>
329 struct MoveConstructible {
330 constexpr MoveConstructible() = default;
331 constexpr MoveConstructible(const MoveConstructible&) = default;
332 MoveConstructible(MoveConstructible&& that) noexcept(Noexcept) {
333 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
335 MoveConstructible& operator=(const MoveConstructible&) = default;
336 MoveConstructible& operator=(MoveConstructible&&) = default;
339 template <class Derived, bool Noexcept>
340 struct MoveConstructible<Derived, false, Noexcept> {
341 constexpr MoveConstructible() = default;
342 constexpr MoveConstructible(const MoveConstructible&) = default;
343 MoveConstructible(MoveConstructible&&) = delete;
344 MoveConstructible& operator=(const MoveConstructible&) = default;
345 MoveConstructible& operator=(MoveConstructible&&) = default;
348 template <class Derived, bool, bool Noexcept>
349 struct CopyAssignable {
350 constexpr CopyAssignable() = default;
351 constexpr CopyAssignable(const CopyAssignable&) = default;
352 constexpr CopyAssignable(CopyAssignable&&) = default;
353 CopyAssignable& operator=(const CopyAssignable& that) noexcept(Noexcept) {
354 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
357 CopyAssignable& operator=(CopyAssignable&&) = default;
360 template <class Derived, bool Noexcept>
361 struct CopyAssignable<Derived, false, Noexcept> {
362 constexpr CopyAssignable() = default;
363 constexpr CopyAssignable(const CopyAssignable&) = default;
364 constexpr CopyAssignable(CopyAssignable&&) = default;
365 CopyAssignable& operator=(const CopyAssignable&) = delete;
366 CopyAssignable& operator=(CopyAssignable&&) = default;
369 template <class Derived, bool, bool Noexcept>
370 struct MoveAssignable {
371 constexpr MoveAssignable() = default;
372 constexpr MoveAssignable(const MoveAssignable&) = default;
373 constexpr MoveAssignable(MoveAssignable&&) = default;
374 MoveAssignable& operator=(const MoveAssignable&) = default;
375 MoveAssignable& operator=(MoveAssignable&& that) noexcept(Noexcept) {
376 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
381 template <class Derived, bool Noexcept>
382 struct MoveAssignable<Derived, false, Noexcept> {
383 constexpr MoveAssignable() = default;
384 constexpr MoveAssignable(const MoveAssignable&) = default;
385 constexpr MoveAssignable(MoveAssignable&&) = default;
386 MoveAssignable& operator=(const MoveAssignable&) = default;
387 MoveAssignable& operator=(MoveAssignable&& that) = delete;
390 template <class Value, class Error>
391 struct ExpectedStorage<Value, Error, StorageType::eUnion>
392 : ExpectedUnion<Value, Error>,
394 ExpectedStorage<Value, Error, StorageType::eUnion>,
395 StrictAllOf<std::is_copy_constructible, Value, Error>::value,
396 StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::value>,
398 ExpectedStorage<Value, Error, StorageType::eUnion>,
399 StrictAllOf<std::is_move_constructible, Value, Error>::value,
400 StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::value>,
402 ExpectedStorage<Value, Error, StorageType::eUnion>,
403 StrictAllOf<IsCopyable, Value, Error>::value,
404 StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
406 ExpectedStorage<Value, Error, StorageType::eUnion>,
407 StrictAllOf<IsMovable, Value, Error>::value,
408 StrictAllOf<IsNothrowMovable, Value, Error>::value> {
409 using value_type = Value;
410 using error_type = Error;
411 using Base = ExpectedUnion<Value, Error>;
412 template <class E = Error, class = decltype(E{})>
413 constexpr ExpectedStorage() noexcept(noexcept(E{})) : Base{ErrorTag{}} {}
414 ExpectedStorage(const ExpectedStorage&) = default;
415 ExpectedStorage(ExpectedStorage&&) = default;
416 ExpectedStorage& operator=(const ExpectedStorage&) = default;
417 ExpectedStorage& operator=(ExpectedStorage&&) = default;
418 using ExpectedUnion<Value, Error>::ExpectedUnion;
422 void clear() noexcept {
423 switch (this->which_) {
425 this->value().~Value();
428 this->error().~Error();
433 this->which_ = Which::eEmpty;
435 bool uninitializedByException() const noexcept {
436 return this->which_ == Which::eEmpty;
438 template <class... Vs>
439 void assignValue(Vs&&... vs) {
440 if (this->which_ == Which::eValue) {
441 expected_detail::doEmplaceAssign(
442 0, this->value(), static_cast<Vs&&>(vs)...);
445 ::new ((void*)std::addressof(this->value()))
446 Value(static_cast<Vs&&>(vs)...);
447 this->which_ = Which::eValue;
450 template <class... Es>
451 void assignError(Es&&... es) {
452 if (this->which_ == Which::eError) {
453 expected_detail::doEmplaceAssign(
454 0, this->error(), static_cast<Es&&>(es)...);
457 ::new ((void*)std::addressof(this->error()))
458 Error(static_cast<Es&&>(es)...);
459 this->which_ = Which::eError;
462 bool isSelfAssign(const ExpectedStorage* that) const {
465 constexpr bool isSelfAssign(const void*) const {
468 template <class Other>
469 void assign(Other&& that) {
470 if (isSelfAssign(&that)) {
473 switch (that.which_) {
475 this->assignValue(static_cast<Other&&>(that).value());
478 this->assignError(static_cast<Other&&>(that).error());
487 // For small (pointer-sized) trivial types, a struct is faster than a union.
488 template <class Value, class Error>
489 struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
490 using value_type = Value;
491 using error_type = Error;
496 constexpr ExpectedStorage() noexcept
497 : which_(Which::eError), error_{}, value_{} {}
498 explicit constexpr ExpectedStorage(EmptyTag) noexcept
499 : which_(Which::eEmpty), error_{}, value_{} {}
500 template <class... Vs>
501 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
502 noexcept(Value(static_cast<Vs&&>(vs)...)))
503 : which_(Which::eValue), error_{}, value_(static_cast<Vs&&>(vs)...) {}
504 template <class... Es>
505 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
506 noexcept(Error(static_cast<Es&&>(es)...)))
507 : which_(Which::eError), error_(static_cast<Es&&>(es)...), value_{} {}
508 void clear() noexcept {}
509 constexpr static bool uninitializedByException() noexcept {
512 template <class... Vs>
513 void assignValue(Vs&&... vs) {
514 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
515 which_ = Which::eValue;
517 template <class... Es>
518 void assignError(Es&&... es) {
519 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
520 which_ = Which::eError;
522 template <class Other>
523 void assign(Other&& that) {
524 switch (that.which_) {
526 this->assignValue(static_cast<Other&&>(that).value());
529 this->assignError(static_cast<Other&&>(that).error());
539 const Value& value() const& {
543 return std::move(value_);
545 // TODO (t17322426): remove when VS2015 support is deprecated
546 // VS2015 static analyzer incorrectly flags these as unreachable in certain
547 // circumstances. VS2017 does not have this problem on the same code.
549 FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
553 const Error& error() const& {
557 return std::move(error_);
562 namespace expected_detail_ExpectedHelper {
563 // Tricky hack so that Expected::then can handle lambdas that return void
565 inline T&& operator,(T&& t, Unit) noexcept {
566 return static_cast<T&&>(t);
569 struct ExpectedHelper {
570 template <class Error, class T>
571 static constexpr Expected<T, Error> return_(T t) {
572 return folly::makeExpected<Error>(t);
577 class U FOLLY_REQUIRES_TRAILING(
578 expected_detail::IsConvertible<U&&, Error>::value)>
579 static constexpr Expected<T, Error> return_(Expected<T, U> t) {
583 template <class This>
584 static typename std::decay<This>::type then_(This&& ex) {
585 return static_cast<This&&>(ex);
589 // Don't warn about not using the overloaded comma operator.
590 FOLLY_MSVC_DISABLE_WARNING(4913)
595 class E = ExpectedErrorType<This>,
596 class T = ExpectedHelper>
597 static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
598 T::template return_<E>(
599 (std::declval<Fn>()(std::declval<This>().value()), unit)),
600 std::declval<Fns>()...)) {
601 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
603 T::template return_<E>(
604 // Uses the comma operator defined above IFF the lambda
606 (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
607 static_cast<Fns&&>(fns)...);
609 return makeUnexpected(static_cast<This&&>(ex).error());
616 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
617 class Err = decltype(std::declval<No>()(std::declval<This>().error()))
618 FOLLY_REQUIRES_TRAILING(!std::is_void<Err>::value)>
619 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
620 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
621 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
623 throw static_cast<No&&>(no)(static_cast<This&&>(ex).error());
630 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
631 class Err = decltype(std::declval<No>()(std::declval<This&>().error()))
632 FOLLY_REQUIRES_TRAILING(std::is_void<Err>::value)>
633 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
634 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
635 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
637 static_cast<No&&>(no)(ex.error());
638 throw typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess()(
639 static_cast<This&&>(ex).error());
643 } // namespace expected_detail_ExpectedHelper
644 /* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
646 struct UnexpectedTag {};
648 } // namespace expected_detail
651 expected_detail::UnexpectedTag (&)(expected_detail::UnexpectedTag);
653 inline expected_detail::UnexpectedTag unexpected(
654 expected_detail::UnexpectedTag = {}) {
659 * An exception type thrown by Expected on catastrophic logic errors.
661 class BadExpectedAccess : public std::logic_error {
663 BadExpectedAccess() : std::logic_error("bad Expected access") {}
666 namespace expected_detail {
668 [[noreturn]] void throwBadExpectedAccess();
670 } // namespace expected_detail
673 * Unexpected - a helper type used to disambiguate the construction of
674 * Expected objects in the error state.
676 template <class Error>
677 class Unexpected final {
679 friend class Unexpected;
680 template <class V, class E>
681 friend class Expected;
682 friend struct expected_detail::ExpectedHelper;
686 * Unexpected::BadExpectedAccess - An exception type thrown by Expected
687 * when the user tries to access the nested value but the Expected object is
688 * actually storing an error code.
690 class BadExpectedAccess : public folly::BadExpectedAccess {
692 explicit BadExpectedAccess(Error err)
693 : folly::BadExpectedAccess{}, error_(std::move(err)) {}
695 * The error code that was held by the Expected object when the user
696 * erroneously requested the value.
698 Error error() const {
709 Unexpected() = default;
710 Unexpected(const Unexpected&) = default;
711 Unexpected(Unexpected&&) = default;
712 Unexpected& operator=(const Unexpected&) = default;
713 Unexpected& operator=(Unexpected&&) = default;
714 constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {}
715 constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {}
717 template <class Other FOLLY_REQUIRES_TRAILING(
718 std::is_constructible<Error, Other&&>::value)>
719 constexpr /* implicit */ Unexpected(Unexpected<Other> that)
720 : error_(std::move(that.error())) {}
725 template <class Other FOLLY_REQUIRES_TRAILING(
726 std::is_assignable<Error&, Other&&>::value)>
727 Unexpected& operator=(Unexpected<Other> that) {
728 error_ = std::move(that.error());
737 const Error& error() const& {
741 return std::move(error_);
745 struct MakeBadExpectedAccess {
747 BadExpectedAccess operator()(E&& err) const {
748 return BadExpectedAccess(static_cast<E&&>(err));
756 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
757 inline bool operator==(
758 const Unexpected<Error>& lhs,
759 const Unexpected<Error>& rhs) {
760 return lhs.error() == rhs.error();
764 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
765 inline bool operator!=(
766 const Unexpected<Error>& lhs,
767 const Unexpected<Error>& rhs) {
768 return !(lhs == rhs);
772 * For constructing an Unexpected object from an error code. Unexpected objects
773 * are implicitly convertible to Expected object in the error state. Usage is
776 * enum class MyErrorCode { BAD_ERROR, WORSE_ERROR };
777 * Expected<int, MyErrorCode> myAPI() {
779 * return i ? makeExpected<MyErrorCode>(i)
780 * : makeUnexpected(MyErrorCode::BAD_ERROR);
783 template <class Error>
784 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(
786 return Unexpected<typename std::decay<Error>::type>{
787 static_cast<Error&&>(err)};
791 * Expected - For holding a value or an error. Useful as an alternative to
792 * exceptions, for APIs where throwing on failure would be too expensive.
794 * Expected<Value, Error> is a variant over the types Value and Error.
796 * Expected does not offer support for references. Use
797 * Expected<std::reference_wrapper<T>, Error> if your API needs to return a
798 * reference or an error.
800 * Expected offers a continuation-based interface to reduce the boilerplate
801 * of checking error codes. The Expected::then member function takes a lambda
802 * that is to execute should the Expected object contain a value. The return
803 * value of the lambda is wrapped in an Expected and returned. If the lambda is
804 * not executed because the Expected contains an error, the error is returned
805 * immediately in a new Expected object.
807 * Expected<int, Error> funcTheFirst();
808 * Expected<std::string, Error> funcTheSecond() {
809 * return funcTheFirst().then([](int i) { return std::to_string(i); });
812 * The above line of code could more verbosely written as:
814 * Expected<std::string, Error> funcTheSecond() {
815 * if (auto ex = funcTheFirst()) {
816 * return std::to_string(*ex);
818 * return makeUnexpected(ex.error());
821 * Continuations can chain, like:
823 * Expected<D, Error> maybeD = someFunc()
824 * .then([](A a){return B(a);})
825 * .then([](B b){return C(b);})
826 * .then([](C c){return D(c);});
828 * To avoid the redundant error checking that would happen if a call at the
829 * front of the chain returns an error, these call chains can be collaped into
830 * a single call to .then:
832 * Expected<D, Error> maybeD = someFunc()
833 * .then([](A a){return B(a);},
834 * [](B b){return C(b);},
835 * [](C c){return D(c);});
837 * The result of .then() is wrapped into Expected< ~, Error > if it isn't
838 * of that form already. Consider the following code:
840 * extern Expected<std::string, Error> readLineFromIO();
841 * extern Expected<int, Error> parseInt(std::string);
842 * extern int increment(int);
844 * Expected<int, Error> x = readLineFromIO().then(parseInt).then(increment);
846 * From the code above, we see that .then() works both with functions that
847 * return an Expected< ~, Error > (like parseInt) and with ones that return
848 * a plain value (like increment). In the case of parseInt, .then() returns
849 * the result of parseInt as-is. In the case of increment, it wraps the int
850 * that increment returns into an Expected< int, Error >.
852 * Sometimes when using a continuation you would prefer an exception to be
853 * thrown for a value-less Expected. For that you can use .thenOrThrow, as
857 * .thenOrThrow([](A a){return B(a);});
859 * The above call to thenOrThrow will invoke the lambda if the Expected returned
860 * by someFunc() contains a value. Otherwise, it will throw an exception of type
861 * Unexpected<Error>::BadExpectedAccess. If you prefer it throw an exception of
862 * a different type, you can pass a second lambda to thenOrThrow:
865 * .thenOrThrow([](A a){return B(a);},
866 * [](Error e) {throw MyException(e);});
868 * Like C++17's std::variant, Expected offers the almost-never-empty guarantee;
869 * that is, an Expected<Value, Error> almost always contains either a Value or
870 * and Error. Partially-formed Expected objects occur when an assignment to
871 * an Expected object that would change the type of the contained object (Value-
872 * to-Error or vice versa) throws. Trying to access either the contained value
873 * or error object causes Expected to throw folly::BadExpectedAccess.
875 * Expected models OptionalPointee, so calling 'get_pointer(ex)' will return a
876 * pointer to nullptr if the 'ex' is in the error state, and a pointer to the
879 * Expected<int, Error> maybeInt = ...;
880 * if (int* v = get_pointer(maybeInt)) {
881 * cout << *v << endl;
884 template <class Value, class Error>
885 class Expected final : expected_detail::ExpectedStorage<Value, Error> {
886 template <class, class>
887 friend class Expected;
888 template <class, class, expected_detail::StorageType>
889 friend struct expected_detail::ExpectedStorage;
890 friend struct expected_detail::ExpectedHelper;
891 using Base = expected_detail::ExpectedStorage<Value, Error>;
892 using MakeBadExpectedAccess =
893 typename Unexpected<Error>::MakeBadExpectedAccess;
897 const Base& base() const& {
901 return std::move(*this);
905 using value_type = Value;
906 using error_type = Error;
907 using IsTriviallyCopyable = typename expected_detail::
908 StrictAllOf<IsTriviallyCopyable, Value, Error>::type;
911 using rebind = Expected<U, Error>;
914 !std::is_reference<Value>::value,
915 "Expected may not be used with reference types");
917 !std::is_abstract<Value>::value,
918 "Expected may not be used with abstract types");
923 template <class B = Base, class = decltype(B{})>
924 Expected() noexcept(noexcept(B{})) : Base{} {}
925 Expected(const Expected& that) = default;
926 Expected(Expected&& that) = default;
930 class E FOLLY_REQUIRES_TRAILING(
931 !std::is_same<Expected<V, E>, Expected>::value &&
932 std::is_constructible<Value, V&&>::value &&
933 std::is_constructible<Error, E&&>::value)>
934 Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} {
935 *this = std::move(that);
938 FOLLY_REQUIRES(std::is_copy_constructible<Value>::value)
939 constexpr /* implicit */ Expected(const Value& val) noexcept(
940 noexcept(Value(val)))
941 : Base{expected_detail::ValueTag{}, val} {}
943 FOLLY_REQUIRES(std::is_move_constructible<Value>::value)
944 constexpr /* implicit */ Expected(Value&& val) noexcept(
945 noexcept(Value(std::move(val))))
946 : Base{expected_detail::ValueTag{}, std::move(val)} {}
948 template <class T FOLLY_REQUIRES_TRAILING(
949 std::is_convertible<T, Value>::value &&
950 !std::is_convertible<T, Error>::value)>
951 constexpr /* implicit */ Expected(T&& val) noexcept(
952 noexcept(Value(static_cast<T&&>(val))))
953 : Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {}
955 template <class... Ts FOLLY_REQUIRES_TRAILING(
956 std::is_constructible<Value, Ts&&...>::value)>
957 explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
958 noexcept(Value(std::declval<Ts>()...)))
959 : Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {}
963 class... Ts FOLLY_REQUIRES_TRAILING(
964 std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
966 explicit constexpr Expected(
968 std::initializer_list<U> il,
969 Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
970 : Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {}
972 // If overload resolution selects one of these deleted functions, that
973 // means you need to use makeUnexpected
974 /* implicit */ Expected(const Error&) = delete;
975 /* implicit */ Expected(Error&&) = delete;
977 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
978 constexpr Expected(unexpected_t, const Error& err) noexcept(
979 noexcept(Error(err)))
980 : Base{expected_detail::ErrorTag{}, err} {}
982 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
983 constexpr Expected(unexpected_t, Error&& err) noexcept(
984 noexcept(Error(std::move(err))))
985 : Base{expected_detail::ErrorTag{}, std::move(err)} {}
987 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
988 constexpr /* implicit */ Expected(const Unexpected<Error>& err) noexcept(
989 noexcept(Error(err.error())))
990 : Base{expected_detail::ErrorTag{}, err.error()} {}
992 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
993 constexpr /* implicit */ Expected(Unexpected<Error>&& err) noexcept(
994 noexcept(Error(std::move(err.error()))))
995 : Base{expected_detail::ErrorTag{}, std::move(err.error())} {}
998 * Assignment operators
1000 Expected& operator=(const Expected& that) = default;
1001 Expected& operator=(Expected&& that) = default;
1005 class E FOLLY_REQUIRES_TRAILING(
1006 !std::is_same<Expected<V, E>, Expected>::value &&
1007 expected_detail::IsConvertible<V&&, Value>::value &&
1008 expected_detail::IsConvertible<E&&, Error>::value)>
1009 Expected& operator=(Expected<V, E> that) {
1010 this->assign(std::move(that));
1014 FOLLY_REQUIRES(expected_detail::IsCopyable<Value>::value)
1015 Expected& operator=(const Value& val) noexcept(
1016 expected_detail::IsNothrowCopyable<Value>::value) {
1017 this->assignValue(val);
1021 FOLLY_REQUIRES(expected_detail::IsMovable<Value>::value)
1022 Expected& operator=(Value&& val) noexcept(
1023 expected_detail::IsNothrowMovable<Value>::value) {
1024 this->assignValue(std::move(val));
1028 template <class T FOLLY_REQUIRES_TRAILING(
1029 std::is_convertible<T, Value>::value &&
1030 !std::is_convertible<T, Error>::value)>
1031 Expected& operator=(T&& val) {
1032 this->assignValue(static_cast<T&&>(val));
1036 FOLLY_REQUIRES(expected_detail::IsCopyable<Error>::value)
1037 Expected& operator=(const Unexpected<Error>& err) noexcept(
1038 expected_detail::IsNothrowCopyable<Error>::value) {
1039 this->assignError(err.error());
1043 FOLLY_REQUIRES(expected_detail::IsMovable<Error>::value)
1044 Expected& operator=(Unexpected<Error>&& err) noexcept(
1045 expected_detail::IsNothrowMovable<Error>::value) {
1046 this->assignError(std::move(err.error()));
1050 // Used only when an Expected is used with coroutines on MSVC
1051 /* implicit */ Expected(const expected_detail::PromiseReturn<Value, Error>& p)
1053 p.promise_->value_ = this;
1056 template <class... Ts FOLLY_REQUIRES_TRAILING(
1057 std::is_constructible<Value, Ts&&...>::value)>
1058 void emplace(Ts&&... ts) {
1059 this->assignValue(static_cast<Ts&&>(ts)...);
1065 void swap(Expected& that) noexcept(
1066 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1067 if (this->uninitializedByException() || that.uninitializedByException()) {
1068 expected_detail::throwBadExpectedAccess();
1073 swap(this->value_, that.value_);
1075 Error e(std::move(that.error_));
1076 that.assignValue(std::move(this->value_));
1077 this->assignError(std::move(e));
1081 swap(this->error_, that.error_);
1083 Error e(std::move(this->error_));
1084 this->assignValue(std::move(that.value_));
1085 that.assignError(std::move(e));
1090 // If overload resolution selects one of these deleted functions, that
1091 // means you need to use makeUnexpected
1092 /* implicit */ Expected& operator=(const Error&) = delete;
1093 /* implicit */ Expected& operator=(Error&&) = delete;
1096 * Relational Operators
1098 template <class Val, class Err>
1099 friend typename std::enable_if<IsEqualityComparable<Val>::value, bool>::type
1100 operator==(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1101 template <class Val, class Err>
1102 friend typename std::enable_if<IsLessThanComparable<Val>::value, bool>::type
1103 operator<(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1108 constexpr bool hasValue() const noexcept {
1109 return expected_detail::Which::eValue == this->which_;
1112 constexpr bool hasError() const noexcept {
1113 return expected_detail::Which::eError == this->which_;
1116 using Base::uninitializedByException;
1118 const Value& value() const& {
1120 return this->Base::value();
1125 return this->Base::value();
1128 Value&& value() && {
1130 return std::move(this->Base::value());
1133 const Error& error() const& {
1135 return this->Base::error();
1140 return this->Base::error();
1143 Error&& error() && {
1145 return std::move(this->Base::error());
1148 // Return a copy of the value if set, or a given default if not.
1150 Value value_or(U&& dflt) const& {
1151 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1152 return this->value_;
1154 return static_cast<U&&>(dflt);
1158 Value value_or(U&& dflt) && {
1159 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1160 return std::move(this->value_);
1162 return static_cast<U&&>(dflt);
1165 explicit constexpr operator bool() const noexcept {
1169 const Value& operator*() const& {
1170 return this->value();
1173 Value& operator*() & {
1174 return this->value();
1177 Value&& operator*() && {
1178 return std::move(this->value());
1181 const Value* operator->() const {
1182 return std::addressof(this->value());
1185 Value* operator->() {
1186 return std::addressof(this->value());
1189 const Value* get_pointer() const& noexcept {
1190 return hasValue() ? std::addressof(this->value_) : nullptr;
1193 Value* get_pointer() & noexcept {
1194 return hasValue() ? std::addressof(this->value_) : nullptr;
1197 Value* get_pointer() && = delete;
1202 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1203 auto then(Fns&&... fns) const& -> decltype(
1204 expected_detail::ExpectedHelper::then_(
1205 std::declval<const Base&>(),
1206 std::declval<Fns>()...)) {
1207 if (this->uninitializedByException()) {
1208 expected_detail::throwBadExpectedAccess();
1210 return expected_detail::ExpectedHelper::then_(
1211 base(), static_cast<Fns&&>(fns)...);
1214 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1215 auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1216 std::declval<Base&>(),
1217 std::declval<Fns>()...)) {
1218 if (this->uninitializedByException()) {
1219 expected_detail::throwBadExpectedAccess();
1221 return expected_detail::ExpectedHelper::then_(
1222 base(), static_cast<Fns&&>(fns)...);
1225 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1226 auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1227 std::declval<Base&&>(),
1228 std::declval<Fns>()...)) {
1229 if (this->uninitializedByException()) {
1230 expected_detail::throwBadExpectedAccess();
1232 return expected_detail::ExpectedHelper::then_(
1233 std::move(base()), static_cast<Fns&&>(fns)...);
1239 template <class Yes, class No = MakeBadExpectedAccess>
1240 auto thenOrThrow(Yes&& yes, No&& no = No{}) const& -> decltype(
1241 std::declval<Yes>()(std::declval<const Value&>())) {
1242 using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1243 if (this->uninitializedByException()) {
1244 expected_detail::throwBadExpectedAccess();
1246 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1247 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1250 template <class Yes, class No = MakeBadExpectedAccess>
1251 auto thenOrThrow(Yes&& yes, No&& no = No{}) & -> decltype(
1252 std::declval<Yes>()(std::declval<Value&>())) {
1253 using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1254 if (this->uninitializedByException()) {
1255 expected_detail::throwBadExpectedAccess();
1257 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1258 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1261 template <class Yes, class No = MakeBadExpectedAccess>
1262 auto thenOrThrow(Yes&& yes, No&& no = No{}) && -> decltype(
1263 std::declval<Yes>()(std::declval<Value&&>())) {
1264 using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1265 if (this->uninitializedByException()) {
1266 expected_detail::throwBadExpectedAccess();
1268 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1269 std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1273 void requireValue() const {
1274 if (UNLIKELY(!hasValue())) {
1275 if (LIKELY(hasError())) {
1276 throw typename Unexpected<Error>::BadExpectedAccess(this->error_);
1278 expected_detail::throwBadExpectedAccess();
1282 void requireError() const {
1283 if (UNLIKELY(!hasError())) {
1284 expected_detail::throwBadExpectedAccess();
1288 expected_detail::Which which() const noexcept {
1289 return this->which_;
1293 template <class Value, class Error>
1294 inline typename std::enable_if<IsEqualityComparable<Value>::value, bool>::type
1296 const Expected<Value, Error>& lhs,
1297 const Expected<Value, Error>& rhs) {
1298 if (UNLIKELY(lhs.uninitializedByException())) {
1299 expected_detail::throwBadExpectedAccess();
1301 if (UNLIKELY(lhs.which_ != rhs.which_)) {
1304 if (UNLIKELY(lhs.hasError())) {
1305 return true; // All error states are considered equal
1307 return lhs.value_ == rhs.value_;
1312 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Value>::value)>
1313 inline bool operator!=(
1314 const Expected<Value, Error>& lhs,
1315 const Expected<Value, Error>& rhs) {
1316 return !(rhs == lhs);
1319 template <class Value, class Error>
1320 inline typename std::enable_if<IsLessThanComparable<Value>::value, bool>::type
1322 const Expected<Value, Error>& lhs,
1323 const Expected<Value, Error>& rhs) {
1325 lhs.uninitializedByException() || rhs.uninitializedByException())) {
1326 expected_detail::throwBadExpectedAccess();
1328 if (UNLIKELY(lhs.hasError())) {
1329 return !rhs.hasError();
1331 if (UNLIKELY(rhs.hasError())) {
1334 return lhs.value_ < rhs.value_;
1339 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1340 inline bool operator<=(
1341 const Expected<Value, Error>& lhs,
1342 const Expected<Value, Error>& rhs) {
1343 return !(rhs < lhs);
1348 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1349 inline bool operator>(
1350 const Expected<Value, Error>& lhs,
1351 const Expected<Value, Error>& rhs) {
1357 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1358 inline bool operator>=(
1359 const Expected<Value, Error>& lhs,
1360 const Expected<Value, Error>& rhs) {
1361 return !(lhs < rhs);
1365 * swap Expected values
1367 template <class Error, class Value>
1368 void swap(Expected<Error, Value>& lhs, Expected<Value, Error>& rhs) noexcept(
1369 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1373 template <class Value, class Error>
1374 const Value* get_pointer(const Expected<Value, Error>& ex) noexcept {
1375 return ex.get_pointer();
1378 template <class Value, class Error>
1379 Value* get_pointer(Expected<Value, Error>& ex) noexcept {
1380 return ex.get_pointer();
1384 * For constructing an Expected object from a value, with the specified
1385 * Error type. Usage is as follows:
1387 * enum MyErrorCode { BAD_ERROR, WORSE_ERROR };
1388 * Expected<int, MyErrorCode> myAPI() {
1390 * return i ? makeExpected<MyErrorCode>(i) : makeUnexpected(BAD_ERROR);
1393 template <class Error, class Value>
1394 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
1396 return Expected<typename std::decay<Value>::type, Error>{
1397 in_place, static_cast<Value&&>(val)};
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;
1426 } // namespace folly
1428 #if defined(__GNUC__) && !defined(__clang__)
1429 #pragma GCC diagnostic pop
1432 #undef FOLLY_REQUIRES
1433 #undef FOLLY_REQUIRES_TRAILING
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>
1441 namespace expected_detail {
1442 template <typename Value, typename Error>
1445 template <typename Value, typename Error>
1446 struct PromiseReturn {
1447 Optional<Expected<Value, Error>> storage_;
1448 Promise<Value, Error>* promise_;
1449 /* implicit */ PromiseReturn(Promise<Value, Error>& promise) noexcept
1450 : promise_(&promise) {
1451 promise_->value_ = &storage_;
1453 PromiseReturn(PromiseReturn&& that) noexcept
1454 : PromiseReturn{*that.promise_} {}
1456 /* implicit */ operator Expected<Value, Error>() & {
1457 return std::move(*storage_);
1461 template <typename Value, typename Error>
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
1469 // auto retobj = p.get_return_object(); // clang
1470 PromiseReturn<Value, Error> get_return_object() noexcept {
1473 std::experimental::suspend_never initial_suspend() const noexcept {
1476 std::experimental::suspend_never final_suspend() const {
1479 template <typename U>
1480 void return_value(U&& u) {
1481 value_->emplace(static_cast<U&&>(u));
1483 void unhandled_exception() {
1484 // Technically, throwing from unhandled_exception is underspecified:
1485 // https://github.com/GorNishanov/CoroutineWording/issues/17
1490 template <typename Value, typename Error>
1492 Expected<Value, Error> o_;
1494 explicit Awaitable(Expected<Value, Error> o) : o_(std::move(o)) {}
1496 bool await_ready() const noexcept {
1497 return o_.hasValue();
1499 Value await_resume() {
1500 return std::move(o_.value());
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
1511 } // namespace expected_detail
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)};
1518 } // namespace folly
1520 // This makes folly::Optional<Value> useable as a coroutine return type..
1521 FOLLY_NAMESPACE_STD_BEGIN
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>;
1527 } // namespace experimental
1528 FOLLY_NAMESPACE_STD_END
1529 #endif // FOLLY_HAS_COROUTINES