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>
43 #define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__)
45 #define FOLLY_REQUIRES_IMPL(...) \
46 bool FOLLY_EXPECTED_ID(Requires) = false, \
47 typename std::enable_if< \
48 (FOLLY_EXPECTED_ID(Requires) || static_cast<bool>(__VA_ARGS__)), \
51 #define FOLLY_REQUIRES_TRAILING(...) , FOLLY_REQUIRES_IMPL(__VA_ARGS__)
53 #define FOLLY_REQUIRES(...) template <FOLLY_REQUIRES_IMPL(__VA_ARGS__)>
56 * gcc-4.7 warns about use of uninitialized memory around the use of storage_
57 * even though this is explicitly initialized at each point.
59 #if defined(__GNUC__) && !defined(__clang__)
60 #pragma GCC diagnostic push
61 #pragma GCC diagnostic ignored "-Wuninitialized"
62 #pragma GCC diagnostic ignored "-Wpragmas"
63 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
69 * Forward declarations
71 template <class Error>
74 template <class Error>
75 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(Error&&);
77 template <class Value, class Error>
80 template <class Error, class Value>
81 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
85 * Alias for an Expected type's assiciated value_type
87 template <class Expected>
88 using ExpectedValueType =
89 typename std::remove_reference<Expected>::type::value_type;
92 * Alias for an Expected type's assiciated error_type
94 template <class Expected>
95 using ExpectedErrorType =
96 typename std::remove_reference<Expected>::type::error_type;
99 namespace expected_detail {
101 template <typename Value, typename Error>
102 struct PromiseReturn;
105 // MSVC 2015 can't handle the StrictConjunction, so we have
106 // to use std::conjunction instead.
107 template <template <class...> class Trait, class... Ts>
108 using StrictAllOf = std::conjunction<Trait<Ts>...>;
110 template <template <class...> class Trait, class... Ts>
111 using StrictAllOf = StrictConjunction<Trait<Ts>...>;
115 using IsCopyable = StrictConjunction<
116 std::is_copy_constructible<T>,
117 std::is_copy_assignable<T>>;
120 using IsMovable = StrictConjunction<
121 std::is_move_constructible<T>,
122 std::is_move_assignable<T>>;
125 using IsNothrowCopyable = StrictConjunction<
126 std::is_nothrow_copy_constructible<T>,
127 std::is_nothrow_copy_assignable<T>>;
130 using IsNothrowMovable = StrictConjunction<
131 std::is_nothrow_move_constructible<T>,
132 std::is_nothrow_move_assignable<T>>;
134 template <class From, class To>
135 using IsConvertible = StrictConjunction<
136 std::is_constructible<To, From>,
137 std::is_assignable<To&, From>>;
139 template <class T, class U>
140 auto doEmplaceAssign(int, T& t, U&& u) -> decltype(void(t = (U &&)u)) {
144 template <class T, class U>
145 auto doEmplaceAssign(long, T& t, U&& u) -> decltype(void(T((U &&)u))) {
147 ::new ((void*)std::addressof(t)) T((U &&)u);
150 template <class T, class... Us>
151 auto doEmplaceAssign(int, T& t, Us&&... us)
152 -> decltype(void(t = T((Us &&)us...))) {
156 template <class T, class... Us>
157 auto doEmplaceAssign(long, T& t, Us&&... us)
158 -> decltype(void(T((Us &&)us...))) {
160 ::new ((void*)std::addressof(t)) T((Us &&)us...);
166 enum class Which : unsigned char { eEmpty, eValue, eError };
167 enum class StorageType { ePODStruct, ePODUnion, eUnion };
169 template <class Value, class Error>
170 constexpr StorageType getStorageType() {
171 return StrictAllOf<IsTriviallyCopyable, Value, Error>::value
172 ? (sizeof(std::pair<Value, Error>) <= sizeof(void * [2]) &&
173 StrictAllOf<std::is_trivial, Value, Error>::value
174 ? StorageType::ePODStruct
175 : StorageType::ePODUnion)
176 : StorageType::eUnion;
182 StorageType = expected_detail::getStorageType<Value, Error>()> // ePODUnion
183 struct ExpectedStorage {
184 using value_type = Value;
185 using error_type = Error;
193 template <class E = Error, class = decltype(E{})>
194 constexpr ExpectedStorage() noexcept(noexcept(E{}))
195 : error_{}, which_(Which::eError) {}
196 explicit constexpr ExpectedStorage(EmptyTag) noexcept
197 : ch_{}, which_(Which::eEmpty) {}
198 template <class... Vs>
199 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
200 noexcept(Value(static_cast<Vs&&>(vs)...)))
201 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
202 template <class... Es>
203 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
204 noexcept(Error(static_cast<Es&&>(es)...)))
205 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
206 void clear() noexcept {}
207 static constexpr bool uninitializedByException() noexcept {
208 // Although which_ may temporarily be eEmpty during construction, it
209 // is always either eValue or eError for a fully-constructed Expected.
212 template <class... Vs>
213 void assignValue(Vs&&... vs) {
214 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
215 which_ = Which::eValue;
217 template <class... Es>
218 void assignError(Es&&... es) {
219 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
220 which_ = Which::eError;
222 template <class Other>
223 void assign(Other&& that) {
224 switch (that.which_) {
226 this->assignValue(static_cast<Other&&>(that).value());
229 this->assignError(static_cast<Other&&>(that).error());
239 const Value& value() const& {
243 return std::move(value_);
245 // TODO (t17322426): remove when VS2015 support is deprecated
246 // VS2015 static analyzer incorrectly flags these as unreachable in certain
247 // circumstances. VS2017 does not have this problem on the same code.
249 FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
253 const Error& error() const& {
257 return std::move(error_);
262 template <class Value, class Error>
263 struct ExpectedUnion {
269 Which which_ = Which::eEmpty;
271 explicit constexpr ExpectedUnion(EmptyTag) noexcept {}
272 template <class... Vs>
273 explicit constexpr ExpectedUnion(ValueTag, Vs&&... vs) noexcept(
274 noexcept(Value(static_cast<Vs&&>(vs)...)))
275 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
276 template <class... Es>
277 explicit constexpr ExpectedUnion(ErrorTag, Es&&... es) noexcept(
278 noexcept(Error(static_cast<Es&&>(es)...)))
279 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
280 ExpectedUnion(const ExpectedUnion&) {}
281 ExpectedUnion(ExpectedUnion&&) noexcept {}
282 ExpectedUnion& operator=(const ExpectedUnion&) {
285 ExpectedUnion& operator=(ExpectedUnion&&) noexcept {
292 const Value& value() const& {
296 return std::move(value_);
301 const Error& error() const& {
305 return std::move(error_);
309 template <class Derived, bool, bool Noexcept>
310 struct CopyConstructible {
311 constexpr CopyConstructible() = default;
312 CopyConstructible(const CopyConstructible& that) noexcept(Noexcept) {
313 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
315 constexpr CopyConstructible(CopyConstructible&&) = default;
316 CopyConstructible& operator=(const CopyConstructible&) = default;
317 CopyConstructible& operator=(CopyConstructible&&) = default;
320 template <class Derived, bool Noexcept>
321 struct CopyConstructible<Derived, false, Noexcept> {
322 constexpr CopyConstructible() = default;
323 CopyConstructible(const CopyConstructible&) = delete;
324 constexpr CopyConstructible(CopyConstructible&&) = default;
325 CopyConstructible& operator=(const CopyConstructible&) = default;
326 CopyConstructible& operator=(CopyConstructible&&) = default;
329 template <class Derived, bool, bool Noexcept>
330 struct MoveConstructible {
331 constexpr MoveConstructible() = default;
332 constexpr MoveConstructible(const MoveConstructible&) = default;
333 MoveConstructible(MoveConstructible&& that) noexcept(Noexcept) {
334 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
336 MoveConstructible& operator=(const MoveConstructible&) = default;
337 MoveConstructible& operator=(MoveConstructible&&) = default;
340 template <class Derived, bool Noexcept>
341 struct MoveConstructible<Derived, false, Noexcept> {
342 constexpr MoveConstructible() = default;
343 constexpr MoveConstructible(const MoveConstructible&) = default;
344 MoveConstructible(MoveConstructible&&) = delete;
345 MoveConstructible& operator=(const MoveConstructible&) = default;
346 MoveConstructible& operator=(MoveConstructible&&) = default;
349 template <class Derived, bool, bool Noexcept>
350 struct CopyAssignable {
351 constexpr CopyAssignable() = default;
352 constexpr CopyAssignable(const CopyAssignable&) = default;
353 constexpr CopyAssignable(CopyAssignable&&) = default;
354 CopyAssignable& operator=(const CopyAssignable& that) noexcept(Noexcept) {
355 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
358 CopyAssignable& operator=(CopyAssignable&&) = default;
361 template <class Derived, bool Noexcept>
362 struct CopyAssignable<Derived, false, Noexcept> {
363 constexpr CopyAssignable() = default;
364 constexpr CopyAssignable(const CopyAssignable&) = default;
365 constexpr CopyAssignable(CopyAssignable&&) = default;
366 CopyAssignable& operator=(const CopyAssignable&) = delete;
367 CopyAssignable& operator=(CopyAssignable&&) = default;
370 template <class Derived, bool, bool Noexcept>
371 struct MoveAssignable {
372 constexpr MoveAssignable() = default;
373 constexpr MoveAssignable(const MoveAssignable&) = default;
374 constexpr MoveAssignable(MoveAssignable&&) = default;
375 MoveAssignable& operator=(const MoveAssignable&) = default;
376 MoveAssignable& operator=(MoveAssignable&& that) noexcept(Noexcept) {
377 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
382 template <class Derived, bool Noexcept>
383 struct MoveAssignable<Derived, false, Noexcept> {
384 constexpr MoveAssignable() = default;
385 constexpr MoveAssignable(const MoveAssignable&) = default;
386 constexpr MoveAssignable(MoveAssignable&&) = default;
387 MoveAssignable& operator=(const MoveAssignable&) = default;
388 MoveAssignable& operator=(MoveAssignable&& that) = delete;
391 template <class Value, class Error>
392 struct ExpectedStorage<Value, Error, StorageType::eUnion>
393 : ExpectedUnion<Value, Error>,
395 ExpectedStorage<Value, Error, StorageType::eUnion>,
396 StrictAllOf<std::is_copy_constructible, Value, Error>::value,
397 StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::value>,
399 ExpectedStorage<Value, Error, StorageType::eUnion>,
400 StrictAllOf<std::is_move_constructible, Value, Error>::value,
401 StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::value>,
403 ExpectedStorage<Value, Error, StorageType::eUnion>,
404 StrictAllOf<IsCopyable, Value, Error>::value,
405 StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
407 ExpectedStorage<Value, Error, StorageType::eUnion>,
408 StrictAllOf<IsMovable, Value, Error>::value,
409 StrictAllOf<IsNothrowMovable, Value, Error>::value> {
410 using value_type = Value;
411 using error_type = Error;
412 using Base = ExpectedUnion<Value, Error>;
413 template <class E = Error, class = decltype(E{})>
414 constexpr ExpectedStorage() noexcept(noexcept(E{})) : Base{ErrorTag{}} {}
415 ExpectedStorage(const ExpectedStorage&) = default;
416 ExpectedStorage(ExpectedStorage&&) = default;
417 ExpectedStorage& operator=(const ExpectedStorage&) = default;
418 ExpectedStorage& operator=(ExpectedStorage&&) = default;
419 using ExpectedUnion<Value, Error>::ExpectedUnion;
423 void clear() noexcept {
424 switch (this->which_) {
426 this->value().~Value();
429 this->error().~Error();
434 this->which_ = Which::eEmpty;
436 bool uninitializedByException() const noexcept {
437 return this->which_ == Which::eEmpty;
439 template <class... Vs>
440 void assignValue(Vs&&... vs) {
441 if (this->which_ == Which::eValue) {
442 expected_detail::doEmplaceAssign(
443 0, this->value(), static_cast<Vs&&>(vs)...);
446 ::new ((void*)std::addressof(this->value()))
447 Value(static_cast<Vs&&>(vs)...);
448 this->which_ = Which::eValue;
451 template <class... Es>
452 void assignError(Es&&... es) {
453 if (this->which_ == Which::eError) {
454 expected_detail::doEmplaceAssign(
455 0, this->error(), static_cast<Es&&>(es)...);
458 ::new ((void*)std::addressof(this->error()))
459 Error(static_cast<Es&&>(es)...);
460 this->which_ = Which::eError;
463 bool isSelfAssign(const ExpectedStorage* that) const {
466 constexpr bool isSelfAssign(const void*) const {
469 template <class Other>
470 void assign(Other&& that) {
471 if (isSelfAssign(&that)) {
474 switch (that.which_) {
476 this->assignValue(static_cast<Other&&>(that).value());
479 this->assignError(static_cast<Other&&>(that).error());
488 // For small (pointer-sized) trivial types, a struct is faster than a union.
489 template <class Value, class Error>
490 struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
491 using value_type = Value;
492 using error_type = Error;
497 constexpr ExpectedStorage() noexcept
498 : which_(Which::eError), error_{}, value_{} {}
499 explicit constexpr ExpectedStorage(EmptyTag) noexcept
500 : which_(Which::eEmpty), error_{}, value_{} {}
501 template <class... Vs>
502 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
503 noexcept(Value(static_cast<Vs&&>(vs)...)))
504 : which_(Which::eValue), error_{}, value_(static_cast<Vs&&>(vs)...) {}
505 template <class... Es>
506 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
507 noexcept(Error(static_cast<Es&&>(es)...)))
508 : which_(Which::eError), error_(static_cast<Es&&>(es)...), value_{} {}
509 void clear() noexcept {}
510 constexpr static bool uninitializedByException() noexcept {
513 template <class... Vs>
514 void assignValue(Vs&&... vs) {
515 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
516 which_ = Which::eValue;
518 template <class... Es>
519 void assignError(Es&&... es) {
520 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
521 which_ = Which::eError;
523 template <class Other>
524 void assign(Other&& that) {
525 switch (that.which_) {
527 this->assignValue(static_cast<Other&&>(that).value());
530 this->assignError(static_cast<Other&&>(that).error());
540 const Value& value() const& {
544 return std::move(value_);
546 // TODO (t17322426): remove when VS2015 support is deprecated
547 // VS2015 static analyzer incorrectly flags these as unreachable in certain
548 // circumstances. VS2017 does not have this problem on the same code.
550 FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
554 const Error& error() const& {
558 return std::move(error_);
563 namespace expected_detail_ExpectedHelper {
564 // Tricky hack so that Expected::then can handle lambdas that return void
566 inline T&& operator,(T&& t, Unit) noexcept {
567 return static_cast<T&&>(t);
570 struct ExpectedHelper {
571 template <class Error, class T>
572 static constexpr Expected<T, Error> return_(T t) {
573 return folly::makeExpected<Error>(t);
578 class U FOLLY_REQUIRES_TRAILING(
579 expected_detail::IsConvertible<U&&, Error>::value)>
580 static constexpr Expected<T, Error> return_(Expected<T, U> t) {
584 template <class This>
585 static typename std::decay<This>::type then_(This&& ex) {
586 return static_cast<This&&>(ex);
590 // Don't warn about not using the overloaded comma operator.
591 FOLLY_MSVC_DISABLE_WARNING(4913)
596 class E = ExpectedErrorType<This>,
597 class T = ExpectedHelper>
598 static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
599 T::template return_<E>(
600 (std::declval<Fn>()(std::declval<This>().value()), unit)),
601 std::declval<Fns>()...)) {
602 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
604 T::template return_<E>(
605 // Uses the comma operator defined above IFF the lambda
607 (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
608 static_cast<Fns&&>(fns)...);
610 return makeUnexpected(static_cast<This&&>(ex).error());
617 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
618 class Err = decltype(std::declval<No>()(std::declval<This>().error()))
619 FOLLY_REQUIRES_TRAILING(!std::is_void<Err>::value)>
620 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
621 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
622 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
624 throw static_cast<No&&>(no)(static_cast<This&&>(ex).error());
631 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
632 class Err = decltype(std::declval<No>()(std::declval<This&>().error()))
633 FOLLY_REQUIRES_TRAILING(std::is_void<Err>::value)>
634 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
635 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
636 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
638 static_cast<No&&>(no)(ex.error());
639 throw typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess()(
640 static_cast<This&&>(ex).error());
644 } // namespace expected_detail_ExpectedHelper
645 /* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
647 struct UnexpectedTag {};
649 } // namespace expected_detail
652 expected_detail::UnexpectedTag (&)(expected_detail::UnexpectedTag);
654 inline expected_detail::UnexpectedTag unexpected(
655 expected_detail::UnexpectedTag = {}) {
660 * An exception type thrown by Expected on catastrophic logic errors.
662 class BadExpectedAccess : public std::logic_error {
664 BadExpectedAccess() : std::logic_error("bad Expected access") {}
667 namespace expected_detail {
669 [[noreturn]] void throwBadExpectedAccess();
671 } // namespace expected_detail
674 * Unexpected - a helper type used to disambiguate the construction of
675 * Expected objects in the error state.
677 template <class Error>
678 class Unexpected final {
680 friend class Unexpected;
681 template <class V, class E>
682 friend class Expected;
683 friend struct expected_detail::ExpectedHelper;
687 * Unexpected::BadExpectedAccess - An exception type thrown by Expected
688 * when the user tries to access the nested value but the Expected object is
689 * actually storing an error code.
691 class BadExpectedAccess : public folly::BadExpectedAccess {
693 explicit BadExpectedAccess(Error err)
694 : folly::BadExpectedAccess{}, error_(std::move(err)) {}
696 * The error code that was held by the Expected object when the user
697 * erroneously requested the value.
699 Error error() const {
710 Unexpected() = default;
711 Unexpected(const Unexpected&) = default;
712 Unexpected(Unexpected&&) = default;
713 Unexpected& operator=(const Unexpected&) = default;
714 Unexpected& operator=(Unexpected&&) = default;
715 FOLLY_COLD constexpr /* implicit */ Unexpected(const Error& err)
717 FOLLY_COLD constexpr /* implicit */ Unexpected(Error&& err)
718 : error_(std::move(err)) {}
720 template <class Other FOLLY_REQUIRES_TRAILING(
721 std::is_constructible<Error, Other&&>::value)>
722 constexpr /* implicit */ Unexpected(Unexpected<Other> that)
723 : error_(std::move(that.error())) {}
728 template <class Other FOLLY_REQUIRES_TRAILING(
729 std::is_assignable<Error&, Other&&>::value)>
730 Unexpected& operator=(Unexpected<Other> that) {
731 error_ = std::move(that.error());
740 const Error& error() const& {
744 return std::move(error_);
748 struct MakeBadExpectedAccess {
750 BadExpectedAccess operator()(E&& err) const {
751 return BadExpectedAccess(static_cast<E&&>(err));
759 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
760 inline bool operator==(
761 const Unexpected<Error>& lhs,
762 const Unexpected<Error>& rhs) {
763 return lhs.error() == rhs.error();
767 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
768 inline bool operator!=(
769 const Unexpected<Error>& lhs,
770 const Unexpected<Error>& rhs) {
771 return !(lhs == rhs);
775 * For constructing an Unexpected object from an error code. Unexpected objects
776 * are implicitly convertible to Expected object in the error state. Usage is
779 * enum class MyErrorCode { BAD_ERROR, WORSE_ERROR };
780 * Expected<int, MyErrorCode> myAPI() {
782 * return i ? makeExpected<MyErrorCode>(i)
783 * : makeUnexpected(MyErrorCode::BAD_ERROR);
786 template <class Error>
787 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(
789 return Unexpected<typename std::decay<Error>::type>{
790 static_cast<Error&&>(err)};
794 * Expected - For holding a value or an error. Useful as an alternative to
795 * exceptions, for APIs where throwing on failure would be too expensive.
797 * Expected<Value, Error> is a variant over the types Value and Error.
799 * Expected does not offer support for references. Use
800 * Expected<std::reference_wrapper<T>, Error> if your API needs to return a
801 * reference or an error.
803 * Expected offers a continuation-based interface to reduce the boilerplate
804 * of checking error codes. The Expected::then member function takes a lambda
805 * that is to execute should the Expected object contain a value. The return
806 * value of the lambda is wrapped in an Expected and returned. If the lambda is
807 * not executed because the Expected contains an error, the error is returned
808 * immediately in a new Expected object.
810 * Expected<int, Error> funcTheFirst();
811 * Expected<std::string, Error> funcTheSecond() {
812 * return funcTheFirst().then([](int i) { return std::to_string(i); });
815 * The above line of code could more verbosely written as:
817 * Expected<std::string, Error> funcTheSecond() {
818 * if (auto ex = funcTheFirst()) {
819 * return std::to_string(*ex);
821 * return makeUnexpected(ex.error());
824 * Continuations can chain, like:
826 * Expected<D, Error> maybeD = someFunc()
827 * .then([](A a){return B(a);})
828 * .then([](B b){return C(b);})
829 * .then([](C c){return D(c);});
831 * To avoid the redundant error checking that would happen if a call at the
832 * front of the chain returns an error, these call chains can be collaped into
833 * a single call to .then:
835 * Expected<D, Error> maybeD = someFunc()
836 * .then([](A a){return B(a);},
837 * [](B b){return C(b);},
838 * [](C c){return D(c);});
840 * The result of .then() is wrapped into Expected< ~, Error > if it isn't
841 * of that form already. Consider the following code:
843 * extern Expected<std::string, Error> readLineFromIO();
844 * extern Expected<int, Error> parseInt(std::string);
845 * extern int increment(int);
847 * Expected<int, Error> x = readLineFromIO().then(parseInt).then(increment);
849 * From the code above, we see that .then() works both with functions that
850 * return an Expected< ~, Error > (like parseInt) and with ones that return
851 * a plain value (like increment). In the case of parseInt, .then() returns
852 * the result of parseInt as-is. In the case of increment, it wraps the int
853 * that increment returns into an Expected< int, Error >.
855 * Sometimes when using a continuation you would prefer an exception to be
856 * thrown for a value-less Expected. For that you can use .thenOrThrow, as
860 * .thenOrThrow([](A a){return B(a);});
862 * The above call to thenOrThrow will invoke the lambda if the Expected returned
863 * by someFunc() contains a value. Otherwise, it will throw an exception of type
864 * Unexpected<Error>::BadExpectedAccess. If you prefer it throw an exception of
865 * a different type, you can pass a second lambda to thenOrThrow:
868 * .thenOrThrow([](A a){return B(a);},
869 * [](Error e) {throw MyException(e);});
871 * Like C++17's std::variant, Expected offers the almost-never-empty guarantee;
872 * that is, an Expected<Value, Error> almost always contains either a Value or
873 * and Error. Partially-formed Expected objects occur when an assignment to
874 * an Expected object that would change the type of the contained object (Value-
875 * to-Error or vice versa) throws. Trying to access either the contained value
876 * or error object causes Expected to throw folly::BadExpectedAccess.
878 * Expected models OptionalPointee, so calling 'get_pointer(ex)' will return a
879 * pointer to nullptr if the 'ex' is in the error state, and a pointer to the
882 * Expected<int, Error> maybeInt = ...;
883 * if (int* v = get_pointer(maybeInt)) {
884 * cout << *v << endl;
887 template <class Value, class Error>
888 class Expected final : expected_detail::ExpectedStorage<Value, Error> {
889 template <class, class>
890 friend class Expected;
891 template <class, class, expected_detail::StorageType>
892 friend struct expected_detail::ExpectedStorage;
893 friend struct expected_detail::ExpectedHelper;
894 using Base = expected_detail::ExpectedStorage<Value, Error>;
895 using MakeBadExpectedAccess =
896 typename Unexpected<Error>::MakeBadExpectedAccess;
900 const Base& base() const& {
904 return std::move(*this);
908 using value_type = Value;
909 using error_type = Error;
910 using IsTriviallyCopyable = typename expected_detail::
911 StrictAllOf<IsTriviallyCopyable, Value, Error>::type;
914 using rebind = Expected<U, Error>;
917 !std::is_reference<Value>::value,
918 "Expected may not be used with reference types");
920 !std::is_abstract<Value>::value,
921 "Expected may not be used with abstract types");
926 template <class B = Base, class = decltype(B{})>
927 Expected() noexcept(noexcept(B{})) : Base{} {}
928 Expected(const Expected& that) = default;
929 Expected(Expected&& that) = default;
933 class E FOLLY_REQUIRES_TRAILING(
934 !std::is_same<Expected<V, E>, Expected>::value &&
935 std::is_constructible<Value, V&&>::value &&
936 std::is_constructible<Error, E&&>::value)>
937 Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} {
938 *this = std::move(that);
941 FOLLY_REQUIRES(std::is_copy_constructible<Value>::value)
942 constexpr /* implicit */ Expected(const Value& val) noexcept(
943 noexcept(Value(val)))
944 : Base{expected_detail::ValueTag{}, val} {}
946 FOLLY_REQUIRES(std::is_move_constructible<Value>::value)
947 constexpr /* implicit */ Expected(Value&& val) noexcept(
948 noexcept(Value(std::move(val))))
949 : Base{expected_detail::ValueTag{}, std::move(val)} {}
951 template <class T FOLLY_REQUIRES_TRAILING(
952 std::is_convertible<T, Value>::value &&
953 !std::is_convertible<T, Error>::value)>
954 constexpr /* implicit */ Expected(T&& val) noexcept(
955 noexcept(Value(static_cast<T&&>(val))))
956 : Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {}
958 template <class... Ts FOLLY_REQUIRES_TRAILING(
959 std::is_constructible<Value, Ts&&...>::value)>
960 explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
961 noexcept(Value(std::declval<Ts>()...)))
962 : Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {}
966 class... Ts FOLLY_REQUIRES_TRAILING(
967 std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
969 explicit constexpr Expected(
971 std::initializer_list<U> il,
972 Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
973 : Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {}
975 // If overload resolution selects one of these deleted functions, that
976 // means you need to use makeUnexpected
977 /* implicit */ Expected(const Error&) = delete;
978 /* implicit */ Expected(Error&&) = delete;
980 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
981 constexpr Expected(unexpected_t, const Error& err) noexcept(
982 noexcept(Error(err)))
983 : Base{expected_detail::ErrorTag{}, err} {}
985 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
986 constexpr Expected(unexpected_t, Error&& err) noexcept(
987 noexcept(Error(std::move(err))))
988 : Base{expected_detail::ErrorTag{}, std::move(err)} {}
990 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
991 constexpr /* implicit */ Expected(const Unexpected<Error>& err) noexcept(
992 noexcept(Error(err.error())))
993 : Base{expected_detail::ErrorTag{}, err.error()} {}
995 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
996 constexpr /* implicit */ Expected(Unexpected<Error>&& err) noexcept(
997 noexcept(Error(std::move(err.error()))))
998 : Base{expected_detail::ErrorTag{}, std::move(err.error())} {}
1001 * Assignment operators
1003 Expected& operator=(const Expected& that) = default;
1004 Expected& operator=(Expected&& that) = default;
1008 class E FOLLY_REQUIRES_TRAILING(
1009 !std::is_same<Expected<V, E>, Expected>::value &&
1010 expected_detail::IsConvertible<V&&, Value>::value &&
1011 expected_detail::IsConvertible<E&&, Error>::value)>
1012 Expected& operator=(Expected<V, E> that) {
1013 this->assign(std::move(that));
1017 FOLLY_REQUIRES(expected_detail::IsCopyable<Value>::value)
1018 Expected& operator=(const Value& val) noexcept(
1019 expected_detail::IsNothrowCopyable<Value>::value) {
1020 this->assignValue(val);
1024 FOLLY_REQUIRES(expected_detail::IsMovable<Value>::value)
1025 Expected& operator=(Value&& val) noexcept(
1026 expected_detail::IsNothrowMovable<Value>::value) {
1027 this->assignValue(std::move(val));
1031 template <class T FOLLY_REQUIRES_TRAILING(
1032 std::is_convertible<T, Value>::value &&
1033 !std::is_convertible<T, Error>::value)>
1034 Expected& operator=(T&& val) {
1035 this->assignValue(static_cast<T&&>(val));
1039 FOLLY_REQUIRES(expected_detail::IsCopyable<Error>::value)
1040 Expected& operator=(const Unexpected<Error>& err) noexcept(
1041 expected_detail::IsNothrowCopyable<Error>::value) {
1042 this->assignError(err.error());
1046 FOLLY_REQUIRES(expected_detail::IsMovable<Error>::value)
1047 Expected& operator=(Unexpected<Error>&& err) noexcept(
1048 expected_detail::IsNothrowMovable<Error>::value) {
1049 this->assignError(std::move(err.error()));
1053 // Used only when an Expected is used with coroutines on MSVC
1054 /* implicit */ Expected(const expected_detail::PromiseReturn<Value, Error>& p)
1056 p.promise_->value_ = this;
1059 template <class... Ts FOLLY_REQUIRES_TRAILING(
1060 std::is_constructible<Value, Ts&&...>::value)>
1061 void emplace(Ts&&... ts) {
1062 this->assignValue(static_cast<Ts&&>(ts)...);
1068 void swap(Expected& that) noexcept(
1069 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1070 if (this->uninitializedByException() || that.uninitializedByException()) {
1071 expected_detail::throwBadExpectedAccess();
1076 swap(this->value_, that.value_);
1078 Error e(std::move(that.error_));
1079 that.assignValue(std::move(this->value_));
1080 this->assignError(std::move(e));
1084 swap(this->error_, that.error_);
1086 Error e(std::move(this->error_));
1087 this->assignValue(std::move(that.value_));
1088 that.assignError(std::move(e));
1093 // If overload resolution selects one of these deleted functions, that
1094 // means you need to use makeUnexpected
1095 /* implicit */ Expected& operator=(const Error&) = delete;
1096 /* implicit */ Expected& operator=(Error&&) = delete;
1099 * Relational Operators
1101 template <class Val, class Err>
1102 friend typename std::enable_if<IsEqualityComparable<Val>::value, bool>::type
1103 operator==(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1104 template <class Val, class Err>
1105 friend typename std::enable_if<IsLessThanComparable<Val>::value, bool>::type
1106 operator<(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1111 constexpr bool hasValue() const noexcept {
1112 return LIKELY(expected_detail::Which::eValue == this->which_);
1115 constexpr bool hasError() const noexcept {
1116 return UNLIKELY(expected_detail::Which::eError == this->which_);
1119 using Base::uninitializedByException;
1121 const Value& value() const& {
1123 return this->Base::value();
1128 return this->Base::value();
1131 Value&& value() && {
1133 return std::move(this->Base::value());
1136 const Error& error() const& {
1138 return this->Base::error();
1143 return this->Base::error();
1146 Error&& error() && {
1148 return std::move(this->Base::error());
1151 // Return a copy of the value if set, or a given default if not.
1153 Value value_or(U&& dflt) const& {
1154 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1155 return this->value_;
1157 return static_cast<U&&>(dflt);
1161 Value value_or(U&& dflt) && {
1162 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1163 return std::move(this->value_);
1165 return static_cast<U&&>(dflt);
1168 explicit constexpr operator bool() const noexcept {
1172 const Value& operator*() const& {
1173 return this->value();
1176 Value& operator*() & {
1177 return this->value();
1180 Value&& operator*() && {
1181 return std::move(this->value());
1184 const Value* operator->() const {
1185 return std::addressof(this->value());
1188 Value* operator->() {
1189 return std::addressof(this->value());
1192 const Value* get_pointer() const& noexcept {
1193 return hasValue() ? std::addressof(this->value_) : nullptr;
1196 Value* get_pointer() & noexcept {
1197 return hasValue() ? std::addressof(this->value_) : nullptr;
1200 Value* get_pointer() && = delete;
1205 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1206 auto then(Fns&&... fns) const& -> decltype(
1207 expected_detail::ExpectedHelper::then_(
1208 std::declval<const Base&>(),
1209 std::declval<Fns>()...)) {
1210 if (this->uninitializedByException()) {
1211 expected_detail::throwBadExpectedAccess();
1213 return expected_detail::ExpectedHelper::then_(
1214 base(), static_cast<Fns&&>(fns)...);
1217 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1218 auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1219 std::declval<Base&>(),
1220 std::declval<Fns>()...)) {
1221 if (this->uninitializedByException()) {
1222 expected_detail::throwBadExpectedAccess();
1224 return expected_detail::ExpectedHelper::then_(
1225 base(), static_cast<Fns&&>(fns)...);
1228 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1229 auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1230 std::declval<Base&&>(),
1231 std::declval<Fns>()...)) {
1232 if (this->uninitializedByException()) {
1233 expected_detail::throwBadExpectedAccess();
1235 return expected_detail::ExpectedHelper::then_(
1236 std::move(base()), static_cast<Fns&&>(fns)...);
1242 template <class Yes, class No = MakeBadExpectedAccess>
1243 auto thenOrThrow(Yes&& yes, No&& no = No{}) const& -> decltype(
1244 std::declval<Yes>()(std::declval<const Value&>())) {
1245 using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1246 if (this->uninitializedByException()) {
1247 expected_detail::throwBadExpectedAccess();
1249 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1250 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1253 template <class Yes, class No = MakeBadExpectedAccess>
1254 auto thenOrThrow(Yes&& yes, No&& no = No{}) & -> decltype(
1255 std::declval<Yes>()(std::declval<Value&>())) {
1256 using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1257 if (this->uninitializedByException()) {
1258 expected_detail::throwBadExpectedAccess();
1260 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1261 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1264 template <class Yes, class No = MakeBadExpectedAccess>
1265 auto thenOrThrow(Yes&& yes, No&& no = No{}) && -> decltype(
1266 std::declval<Yes>()(std::declval<Value&&>())) {
1267 using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1268 if (this->uninitializedByException()) {
1269 expected_detail::throwBadExpectedAccess();
1271 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1272 std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1276 void requireValue() const {
1277 if (UNLIKELY(!hasValue())) {
1278 if (LIKELY(hasError())) {
1279 throw typename Unexpected<Error>::BadExpectedAccess(this->error_);
1281 expected_detail::throwBadExpectedAccess();
1285 void requireError() const {
1286 if (UNLIKELY(!hasError())) {
1287 expected_detail::throwBadExpectedAccess();
1291 expected_detail::Which which() const noexcept {
1292 return this->which_;
1296 template <class Value, class Error>
1297 inline typename std::enable_if<IsEqualityComparable<Value>::value, bool>::type
1299 const Expected<Value, Error>& lhs,
1300 const Expected<Value, Error>& rhs) {
1301 if (UNLIKELY(lhs.uninitializedByException())) {
1302 expected_detail::throwBadExpectedAccess();
1304 if (UNLIKELY(lhs.which_ != rhs.which_)) {
1307 if (UNLIKELY(lhs.hasError())) {
1308 return true; // All error states are considered equal
1310 return lhs.value_ == rhs.value_;
1315 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Value>::value)>
1316 inline bool operator!=(
1317 const Expected<Value, Error>& lhs,
1318 const Expected<Value, Error>& rhs) {
1319 return !(rhs == lhs);
1322 template <class Value, class Error>
1323 inline typename std::enable_if<IsLessThanComparable<Value>::value, bool>::type
1325 const Expected<Value, Error>& lhs,
1326 const Expected<Value, Error>& rhs) {
1328 lhs.uninitializedByException() || rhs.uninitializedByException())) {
1329 expected_detail::throwBadExpectedAccess();
1331 if (UNLIKELY(lhs.hasError())) {
1332 return !rhs.hasError();
1334 if (UNLIKELY(rhs.hasError())) {
1337 return lhs.value_ < rhs.value_;
1342 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1343 inline bool operator<=(
1344 const Expected<Value, Error>& lhs,
1345 const Expected<Value, Error>& rhs) {
1346 return !(rhs < lhs);
1351 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1352 inline bool operator>(
1353 const Expected<Value, Error>& lhs,
1354 const Expected<Value, Error>& rhs) {
1360 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1361 inline bool operator>=(
1362 const Expected<Value, Error>& lhs,
1363 const Expected<Value, Error>& rhs) {
1364 return !(lhs < rhs);
1368 * swap Expected values
1370 template <class Error, class Value>
1371 void swap(Expected<Error, Value>& lhs, Expected<Value, Error>& rhs) noexcept(
1372 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1376 template <class Value, class Error>
1377 const Value* get_pointer(const Expected<Value, Error>& ex) noexcept {
1378 return ex.get_pointer();
1381 template <class Value, class Error>
1382 Value* get_pointer(Expected<Value, Error>& ex) noexcept {
1383 return ex.get_pointer();
1387 * For constructing an Expected object from a value, with the specified
1388 * Error type. Usage is as follows:
1390 * enum MyErrorCode { BAD_ERROR, WORSE_ERROR };
1391 * Expected<int, MyErrorCode> myAPI() {
1393 * return i ? makeExpected<MyErrorCode>(i) : makeUnexpected(BAD_ERROR);
1396 template <class Error, class Value>
1397 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
1399 return Expected<typename std::decay<Value>::type, Error>{
1400 in_place, static_cast<Value&&>(val)};
1403 // Suppress comparability of Optional<T> with T, despite implicit conversion.
1404 template <class Value, class Error>
1405 bool operator==(const Expected<Value, Error>&, const Value& other) = delete;
1406 template <class Value, class Error>
1407 bool operator!=(const Expected<Value, Error>&, const Value& other) = delete;
1408 template <class Value, class Error>
1409 bool operator<(const Expected<Value, Error>&, const Value& other) = delete;
1410 template <class Value, class Error>
1411 bool operator<=(const Expected<Value, Error>&, const Value& other) = delete;
1412 template <class Value, class Error>
1413 bool operator>=(const Expected<Value, Error>&, const Value& other) = delete;
1414 template <class Value, class Error>
1415 bool operator>(const Expected<Value, Error>&, const Value& other) = delete;
1416 template <class Value, class Error>
1417 bool operator==(const Value& other, const Expected<Value, Error>&) = delete;
1418 template <class Value, class Error>
1419 bool operator!=(const Value& other, const Expected<Value, Error>&) = delete;
1420 template <class Value, class Error>
1421 bool operator<(const Value& other, const Expected<Value, Error>&) = delete;
1422 template <class Value, class Error>
1423 bool operator<=(const Value& other, const Expected<Value, Error>&) = delete;
1424 template <class Value, class Error>
1425 bool operator>=(const Value& other, const Expected<Value, Error>&) = delete;
1426 template <class Value, class Error>
1427 bool operator>(const Value& other, const Expected<Value, Error>&) = delete;
1429 } // namespace folly
1431 #if defined(__GNUC__) && !defined(__clang__)
1432 #pragma GCC diagnostic pop
1435 #undef FOLLY_REQUIRES
1436 #undef FOLLY_REQUIRES_TRAILING
1438 // Enable the use of folly::Expected with `co_await`
1439 // Inspired by https://github.com/toby-allsopp/coroutine_monad
1440 #if FOLLY_HAS_COROUTINES
1441 #include <experimental/coroutine>
1444 namespace expected_detail {
1445 template <typename Value, typename Error>
1448 template <typename Value, typename Error>
1449 struct PromiseReturn {
1450 Optional<Expected<Value, Error>> storage_;
1451 Promise<Value, Error>* promise_;
1452 /* implicit */ PromiseReturn(Promise<Value, Error>& promise) noexcept
1453 : promise_(&promise) {
1454 promise_->value_ = &storage_;
1456 PromiseReturn(PromiseReturn&& that) noexcept
1457 : PromiseReturn{*that.promise_} {}
1459 /* implicit */ operator Expected<Value, Error>() & {
1460 return std::move(*storage_);
1464 template <typename Value, typename Error>
1466 Optional<Expected<Value, Error>>* value_ = nullptr;
1467 Promise() = default;
1468 Promise(Promise const&) = delete;
1469 // This should work regardless of whether the compiler generates:
1470 // folly::Expected<Value, Error> retobj{ p.get_return_object(); } // MSVC
1472 // auto retobj = p.get_return_object(); // clang
1473 PromiseReturn<Value, Error> get_return_object() noexcept {
1476 std::experimental::suspend_never initial_suspend() const noexcept {
1479 std::experimental::suspend_never final_suspend() const {
1482 template <typename U>
1483 void return_value(U&& u) {
1484 value_->emplace(static_cast<U&&>(u));
1486 void unhandled_exception() {
1487 // Technically, throwing from unhandled_exception is underspecified:
1488 // https://github.com/GorNishanov/CoroutineWording/issues/17
1493 template <typename Value, typename Error>
1495 Expected<Value, Error> o_;
1497 explicit Awaitable(Expected<Value, Error> o) : o_(std::move(o)) {}
1499 bool await_ready() const noexcept {
1500 return o_.hasValue();
1502 Value await_resume() {
1503 return std::move(o_.value());
1506 // Explicitly only allow suspension into a Promise
1507 template <typename U>
1508 void await_suspend(std::experimental::coroutine_handle<Promise<U, Error>> h) {
1509 *h.promise().value_ = makeUnexpected(std::move(o_.error()));
1510 // Abort the rest of the coroutine. resume() is not going to be called
1514 } // namespace expected_detail
1516 template <typename Value, typename Error>
1517 expected_detail::Awaitable<Value, Error>
1518 /* implicit */ operator co_await(Expected<Value, Error> o) {
1519 return expected_detail::Awaitable<Value, Error>{std::move(o)};
1521 } // namespace folly
1523 // This makes folly::Optional<Value> useable as a coroutine return type..
1524 FOLLY_NAMESPACE_STD_BEGIN
1525 namespace experimental {
1526 template <typename Value, typename Error, typename... Args>
1527 struct coroutine_traits<folly::Expected<Value, Error>, Args...> {
1528 using promise_type = folly::expected_detail::Promise<Value, Error>;
1530 } // namespace experimental
1531 FOLLY_NAMESPACE_STD_END
1532 #endif // FOLLY_HAS_COROUTINES