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 <folly/Likely.h>
33 #include <folly/Portability.h>
34 #include <folly/Preprocessor.h>
35 #include <folly/Traits.h>
36 #include <folly/Unit.h>
37 #include <folly/Utility.h>
39 #define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__)
41 #define FOLLY_REQUIRES_IMPL(...) \
42 bool FOLLY_EXPECTED_ID(Requires) = false, \
43 typename std::enable_if< \
44 (FOLLY_EXPECTED_ID(Requires) || static_cast<bool>(__VA_ARGS__)), \
47 #define FOLLY_REQUIRES_TRAILING(...) , FOLLY_REQUIRES_IMPL(__VA_ARGS__)
49 #define FOLLY_REQUIRES(...) template <FOLLY_REQUIRES_IMPL(__VA_ARGS__)>
52 * gcc-4.7 warns about use of uninitialized memory around the use of storage_
53 * even though this is explicitly initialized at each point.
55 #if defined(__GNUC__) && !defined(__clang__)
56 #pragma GCC diagnostic push
57 #pragma GCC diagnostic ignored "-Wuninitialized"
58 #pragma GCC diagnostic ignored "-Wpragmas"
59 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
65 * Forward declarations
67 template <class Error>
70 template <class Error>
71 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(Error&&);
73 template <class Value, class Error>
76 template <class Error, class Value>
77 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
81 * Alias for an Expected type's assiciated value_type
83 template <class Expected>
84 using ExpectedValueType =
85 typename std::remove_reference<Expected>::type::value_type;
88 * Alias for an Expected type's assiciated error_type
90 template <class Expected>
91 using ExpectedErrorType =
92 typename std::remove_reference<Expected>::type::error_type;
95 namespace expected_detail {
97 // MSVC 2015 can't handle the StrictConjunction, so we have
98 // to use std::conjunction instead.
99 template <template <class...> class Trait, class... Ts>
100 using StrictAllOf = std::conjunction<Trait<Ts>...>;
102 template <template <class...> class Trait, class... Ts>
103 using StrictAllOf = StrictConjunction<Trait<Ts>...>;
107 using IsCopyable = StrictConjunction<
108 std::is_copy_constructible<T>,
109 std::is_copy_assignable<T>>;
112 using IsMovable = StrictConjunction<
113 std::is_move_constructible<T>,
114 std::is_move_assignable<T>>;
117 using IsNothrowCopyable = StrictConjunction<
118 std::is_nothrow_copy_constructible<T>,
119 std::is_nothrow_copy_assignable<T>>;
122 using IsNothrowMovable = StrictConjunction<
123 std::is_nothrow_move_constructible<T>,
124 std::is_nothrow_move_assignable<T>>;
126 template <class From, class To>
127 using IsConvertible = StrictConjunction<
128 std::is_constructible<To, From>,
129 std::is_assignable<To&, From>>;
131 template <class T, class U>
132 auto doEmplaceAssign(int, T& t, U&& u) -> decltype(void(t = (U &&)u)) {
136 template <class T, class U>
137 auto doEmplaceAssign(long, T& t, U&& u) -> decltype(void(T((U &&)u))) {
139 ::new ((void*)std::addressof(t)) T((U &&)u);
142 template <class T, class... Us>
143 auto doEmplaceAssign(int, T& t, Us&&... us)
144 -> decltype(void(t = T((Us &&)us...))) {
148 template <class T, class... Us>
149 auto doEmplaceAssign(long, T& t, Us&&... us)
150 -> decltype(void(T((Us &&)us...))) {
152 ::new ((void*)std::addressof(t)) T((Us &&)us...);
158 enum class Which : unsigned char { eEmpty, eValue, eError };
159 enum class StorageType { ePODStruct, ePODUnion, eUnion };
161 template <class Value, class Error>
162 constexpr StorageType getStorageType() {
163 return StrictAllOf<IsTriviallyCopyable, Value, Error>::value
164 ? (sizeof(std::pair<Value, Error>) <= sizeof(void * [2]) &&
165 StrictAllOf<std::is_trivial, Value, Error>::value
166 ? StorageType::ePODStruct
167 : StorageType::ePODUnion)
168 : StorageType::eUnion;
174 StorageType = expected_detail::getStorageType<Value, Error>()> // ePODUnion
175 struct ExpectedStorage {
176 using value_type = Value;
177 using error_type = Error;
185 template <class E = Error, class = decltype(E{})>
186 constexpr ExpectedStorage() noexcept(noexcept(E{}))
187 : error_{}, which_(Which::eError) {}
188 explicit constexpr ExpectedStorage(EmptyTag) noexcept
189 : ch_{}, which_(Which::eEmpty) {}
190 template <class... Vs>
191 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
192 noexcept(Value(static_cast<Vs&&>(vs)...)))
193 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
194 template <class... Es>
195 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
196 noexcept(Error(static_cast<Es&&>(es)...)))
197 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
198 void clear() noexcept {}
199 static constexpr bool uninitializedByException() noexcept {
200 // Although which_ may temporarily be eEmpty during construction, it
201 // is always either eValue or eError for a fully-constructed Expected.
204 template <class... Vs>
205 void assignValue(Vs&&... vs) {
206 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
207 which_ = Which::eValue;
209 template <class... Es>
210 void assignError(Es&&... es) {
211 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
212 which_ = Which::eError;
214 template <class Other>
215 void assign(Other&& that) {
216 switch (that.which_) {
218 this->assignValue(static_cast<Other&&>(that).value());
221 this->assignError(static_cast<Other&&>(that).error());
231 const Value& value() const& {
235 return std::move(value_);
237 // TODO (t17322426): remove when VS2015 support is deprecated
238 // VS2015 static analyzer incorrectly flags these as unreachable in certain
239 // circumstances. VS2017 does not have this problem on the same code.
241 FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
245 const Error& error() const& {
249 return std::move(error_);
254 template <class Value, class Error>
255 struct ExpectedUnion {
261 Which which_ = Which::eEmpty;
263 explicit constexpr ExpectedUnion(EmptyTag) noexcept {}
264 template <class... Vs>
265 explicit constexpr ExpectedUnion(ValueTag, Vs&&... vs) noexcept(
266 noexcept(Value(static_cast<Vs&&>(vs)...)))
267 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
268 template <class... Es>
269 explicit constexpr ExpectedUnion(ErrorTag, Es&&... es) noexcept(
270 noexcept(Error(static_cast<Es&&>(es)...)))
271 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
272 ExpectedUnion(const ExpectedUnion&) {}
273 ExpectedUnion(ExpectedUnion&&) noexcept {}
274 ExpectedUnion& operator=(const ExpectedUnion&) {
277 ExpectedUnion& operator=(ExpectedUnion&&) noexcept {
284 const Value& value() const& {
288 return std::move(value_);
293 const Error& error() const& {
297 return std::move(error_);
301 template <class Derived, bool, bool Noexcept>
302 struct CopyConstructible {
303 constexpr CopyConstructible() = default;
304 CopyConstructible(const CopyConstructible& that) noexcept(Noexcept) {
305 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
307 constexpr CopyConstructible(CopyConstructible&&) = default;
308 CopyConstructible& operator=(const CopyConstructible&) = default;
309 CopyConstructible& operator=(CopyConstructible&&) = default;
312 template <class Derived, bool Noexcept>
313 struct CopyConstructible<Derived, false, Noexcept> {
314 constexpr CopyConstructible() = default;
315 CopyConstructible(const CopyConstructible&) = delete;
316 constexpr CopyConstructible(CopyConstructible&&) = default;
317 CopyConstructible& operator=(const CopyConstructible&) = default;
318 CopyConstructible& operator=(CopyConstructible&&) = default;
321 template <class Derived, bool, bool Noexcept>
322 struct MoveConstructible {
323 constexpr MoveConstructible() = default;
324 constexpr MoveConstructible(const MoveConstructible&) = default;
325 MoveConstructible(MoveConstructible&& that) noexcept(Noexcept) {
326 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
328 MoveConstructible& operator=(const MoveConstructible&) = default;
329 MoveConstructible& operator=(MoveConstructible&&) = default;
332 template <class Derived, bool Noexcept>
333 struct MoveConstructible<Derived, false, Noexcept> {
334 constexpr MoveConstructible() = default;
335 constexpr MoveConstructible(const MoveConstructible&) = default;
336 MoveConstructible(MoveConstructible&&) = delete;
337 MoveConstructible& operator=(const MoveConstructible&) = default;
338 MoveConstructible& operator=(MoveConstructible&&) = default;
341 template <class Derived, bool, bool Noexcept>
342 struct CopyAssignable {
343 constexpr CopyAssignable() = default;
344 constexpr CopyAssignable(const CopyAssignable&) = default;
345 constexpr CopyAssignable(CopyAssignable&&) = default;
346 CopyAssignable& operator=(const CopyAssignable& that) noexcept(Noexcept) {
347 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
350 CopyAssignable& operator=(CopyAssignable&&) = default;
353 template <class Derived, bool Noexcept>
354 struct CopyAssignable<Derived, false, Noexcept> {
355 constexpr CopyAssignable() = default;
356 constexpr CopyAssignable(const CopyAssignable&) = default;
357 constexpr CopyAssignable(CopyAssignable&&) = default;
358 CopyAssignable& operator=(const CopyAssignable&) = delete;
359 CopyAssignable& operator=(CopyAssignable&&) = default;
362 template <class Derived, bool, bool Noexcept>
363 struct MoveAssignable {
364 constexpr MoveAssignable() = default;
365 constexpr MoveAssignable(const MoveAssignable&) = default;
366 constexpr MoveAssignable(MoveAssignable&&) = default;
367 MoveAssignable& operator=(const MoveAssignable&) = default;
368 MoveAssignable& operator=(MoveAssignable&& that) noexcept(Noexcept) {
369 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
374 template <class Derived, bool Noexcept>
375 struct MoveAssignable<Derived, false, Noexcept> {
376 constexpr MoveAssignable() = default;
377 constexpr MoveAssignable(const MoveAssignable&) = default;
378 constexpr MoveAssignable(MoveAssignable&&) = default;
379 MoveAssignable& operator=(const MoveAssignable&) = default;
380 MoveAssignable& operator=(MoveAssignable&& that) = delete;
383 template <class Value, class Error>
384 struct ExpectedStorage<Value, Error, StorageType::eUnion>
385 : ExpectedUnion<Value, Error>,
387 ExpectedStorage<Value, Error, StorageType::eUnion>,
388 StrictAllOf<std::is_copy_constructible, Value, Error>::value,
389 StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::value>,
391 ExpectedStorage<Value, Error, StorageType::eUnion>,
392 StrictAllOf<std::is_move_constructible, Value, Error>::value,
393 StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::value>,
395 ExpectedStorage<Value, Error, StorageType::eUnion>,
396 StrictAllOf<IsCopyable, Value, Error>::value,
397 StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
399 ExpectedStorage<Value, Error, StorageType::eUnion>,
400 StrictAllOf<IsMovable, Value, Error>::value,
401 StrictAllOf<IsNothrowMovable, Value, Error>::value> {
402 using value_type = Value;
403 using error_type = Error;
404 using Base = ExpectedUnion<Value, Error>;
405 template <class E = Error, class = decltype(E{})>
406 constexpr ExpectedStorage() noexcept(noexcept(E{})) : Base{ErrorTag{}} {}
407 ExpectedStorage(const ExpectedStorage&) = default;
408 ExpectedStorage(ExpectedStorage&&) = default;
409 ExpectedStorage& operator=(const ExpectedStorage&) = default;
410 ExpectedStorage& operator=(ExpectedStorage&&) = default;
411 using ExpectedUnion<Value, Error>::ExpectedUnion;
415 void clear() noexcept {
416 switch (this->which_) {
418 this->value().~Value();
421 this->error().~Error();
426 this->which_ = Which::eEmpty;
428 bool uninitializedByException() const noexcept {
429 return this->which_ == Which::eEmpty;
431 template <class... Vs>
432 void assignValue(Vs&&... vs) {
433 if (this->which_ == Which::eValue) {
434 expected_detail::doEmplaceAssign(
435 0, this->value(), static_cast<Vs&&>(vs)...);
438 ::new ((void*)std::addressof(this->value()))
439 Value(static_cast<Vs&&>(vs)...);
440 this->which_ = Which::eValue;
443 template <class... Es>
444 void assignError(Es&&... es) {
445 if (this->which_ == Which::eError) {
446 expected_detail::doEmplaceAssign(
447 0, this->error(), static_cast<Es&&>(es)...);
450 ::new ((void*)std::addressof(this->error()))
451 Error(static_cast<Es&&>(es)...);
452 this->which_ = Which::eError;
455 bool isSelfAssign(const ExpectedStorage* that) const {
458 constexpr bool isSelfAssign(const void*) const {
461 template <class Other>
462 void assign(Other&& that) {
463 if (isSelfAssign(&that)) {
466 switch (that.which_) {
468 this->assignValue(static_cast<Other&&>(that).value());
471 this->assignError(static_cast<Other&&>(that).error());
480 // For small (pointer-sized) trivial types, a struct is faster than a union.
481 template <class Value, class Error>
482 struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
483 using value_type = Value;
484 using error_type = Error;
489 constexpr ExpectedStorage() noexcept
490 : which_(Which::eError), error_{}, value_{} {}
491 explicit constexpr ExpectedStorage(EmptyTag) noexcept
492 : which_(Which::eEmpty), error_{}, value_{} {}
493 template <class... Vs>
494 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
495 noexcept(Value(static_cast<Vs&&>(vs)...)))
496 : which_(Which::eValue), error_{}, value_(static_cast<Vs&&>(vs)...) {}
497 template <class... Es>
498 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
499 noexcept(Error(static_cast<Es&&>(es)...)))
500 : which_(Which::eError), error_(static_cast<Es&&>(es)...), value_{} {}
501 void clear() noexcept {}
502 constexpr static bool uninitializedByException() noexcept {
505 template <class... Vs>
506 void assignValue(Vs&&... vs) {
507 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
508 which_ = Which::eValue;
510 template <class... Es>
511 void assignError(Es&&... es) {
512 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
513 which_ = Which::eError;
515 template <class Other>
516 void assign(Other&& that) {
517 switch (that.which_) {
519 this->assignValue(static_cast<Other&&>(that).value());
522 this->assignError(static_cast<Other&&>(that).error());
532 const Value& value() const& {
536 return std::move(value_);
538 // TODO (t17322426): remove when VS2015 support is deprecated
539 // VS2015 static analyzer incorrectly flags these as unreachable in certain
540 // circumstances. VS2017 does not have this problem on the same code.
542 FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
546 const Error& error() const& {
550 return std::move(error_);
555 namespace expected_detail_ExpectedHelper {
556 // Tricky hack so that Expected::then can handle lambdas that return void
558 inline T&& operator,(T&& t, Unit) noexcept {
559 return static_cast<T&&>(t);
562 struct ExpectedHelper {
563 template <class Error, class T>
564 static constexpr Expected<T, Error> return_(T t) {
565 return folly::makeExpected<Error>(t);
570 class U FOLLY_REQUIRES_TRAILING(
571 expected_detail::IsConvertible<U&&, Error>::value)>
572 static constexpr Expected<T, Error> return_(Expected<T, U> t) {
576 template <class This>
577 static typename std::decay<This>::type then_(This&& ex) {
578 return static_cast<This&&>(ex);
582 // Don't warn about not using the overloaded comma operator.
583 FOLLY_MSVC_DISABLE_WARNING(4913)
588 class E = ExpectedErrorType<This>,
589 class T = ExpectedHelper>
590 static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
591 T::template return_<E>(
592 (std::declval<Fn>()(std::declval<This>().value()), unit)),
593 std::declval<Fns>()...)) {
594 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
596 T::template return_<E>(
597 // Uses the comma operator defined above IFF the lambda
599 (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
600 static_cast<Fns&&>(fns)...);
602 return makeUnexpected(static_cast<This&&>(ex).error());
609 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
610 class Err = decltype(std::declval<No>()(std::declval<This>().error()))
611 FOLLY_REQUIRES_TRAILING(!std::is_void<Err>::value)>
612 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
613 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
614 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
616 throw static_cast<No&&>(no)(static_cast<This&&>(ex).error());
623 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
624 class Err = decltype(std::declval<No>()(std::declval<This&>().error()))
625 FOLLY_REQUIRES_TRAILING(std::is_void<Err>::value)>
626 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
627 if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
628 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
630 static_cast<No&&>(no)(ex.error());
631 throw typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess()(
632 static_cast<This&&>(ex).error());
637 /* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
639 struct UnexpectedTag {};
641 } // namespace expected_detail
644 expected_detail::UnexpectedTag (&)(expected_detail::UnexpectedTag);
646 inline expected_detail::UnexpectedTag unexpected(
647 expected_detail::UnexpectedTag = {}) {
652 * An exception type thrown by Expected on catastrophic logic errors.
654 class BadExpectedAccess : public std::logic_error {
656 BadExpectedAccess() : std::logic_error("bad Expected access") {}
660 * Unexpected - a helper type used to disambiguate the construction of
661 * Expected objects in the error state.
663 template <class Error>
664 class Unexpected final {
666 friend class Unexpected;
667 template <class V, class E>
668 friend class Expected;
669 friend struct expected_detail::ExpectedHelper;
673 * Unexpected::BadExpectedAccess - An exception type thrown by Expected
674 * when the user tries to access the nested value but the Expected object is
675 * actually storing an error code.
677 class BadExpectedAccess : public folly::BadExpectedAccess {
679 explicit BadExpectedAccess(Error err)
680 : folly::BadExpectedAccess{}, error_(std::move(err)) {}
682 * The error code that was held by the Expected object when the user
683 * erroneously requested the value.
685 Error error() const {
696 Unexpected() = default;
697 Unexpected(const Unexpected&) = default;
698 Unexpected(Unexpected&&) = default;
699 Unexpected& operator=(const Unexpected&) = default;
700 Unexpected& operator=(Unexpected&&) = default;
701 constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {}
702 constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {}
704 template <class Other FOLLY_REQUIRES_TRAILING(
705 std::is_constructible<Error, Other&&>::value)>
706 constexpr /* implicit */ Unexpected(Unexpected<Other> that)
707 : error_(std::move(that.error())) {}
712 template <class Other FOLLY_REQUIRES_TRAILING(
713 std::is_assignable<Error&, Other&&>::value)>
714 Unexpected& operator=(Unexpected<Other> that) {
715 error_ = std::move(that.error());
724 const Error& error() const& {
728 return std::move(error_);
732 struct MakeBadExpectedAccess {
734 BadExpectedAccess operator()(E&& err) const {
735 return BadExpectedAccess(static_cast<E&&>(err));
743 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
744 inline bool operator==(
745 const Unexpected<Error>& lhs,
746 const Unexpected<Error>& rhs) {
747 return lhs.error() == rhs.error();
751 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
752 inline bool operator!=(
753 const Unexpected<Error>& lhs,
754 const Unexpected<Error>& rhs) {
755 return !(lhs == rhs);
759 * For constructing an Unexpected object from an error code. Unexpected objects
760 * are implicitly convertible to Expected object in the error state. Usage is
763 * enum class MyErrorCode { BAD_ERROR, WORSE_ERROR };
764 * Expected<int, MyErrorCode> myAPI() {
766 * return i ? makeExpected<MyErrorCode>(i)
767 * : makeUnexpected(MyErrorCode::BAD_ERROR);
770 template <class Error>
771 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(
773 return Unexpected<typename std::decay<Error>::type>{
774 static_cast<Error&&>(err)};
778 * Expected - For holding a value or an error. Useful as an alternative to
779 * exceptions, for APIs where throwing on failure would be too expensive.
781 * Expected<Value, Error> is a variant over the types Value and Error.
783 * Expected does not offer support for references. Use
784 * Expected<std::reference_wrapper<T>, Error> if your API needs to return a
785 * reference or an error.
787 * Expected offers a continuation-based interface to reduce the boilerplate
788 * of checking error codes. The Expected::then member function takes a lambda
789 * that is to execute should the Expected object contain a value. The return
790 * value of the lambda is wrapped in an Expected and returned. If the lambda is
791 * not executed because the Expected contains an error, the error is returned
792 * immediately in a new Expected object.
794 * Expected<int, Error> funcTheFirst();
795 * Expected<std::string, Error> funcTheSecond() {
796 * return funcTheFirst().then([](int i) { return std::to_string(i); });
799 * The above line of code could more verbosely written as:
801 * Expected<std::string, Error> funcTheSecond() {
802 * if (auto ex = funcTheFirst()) {
803 * return std::to_string(*ex);
805 * return makeUnexpected(ex.error());
808 * Continuations can chain, like:
810 * Expected<D, Error> maybeD = someFunc()
811 * .then([](A a){return B(a);})
812 * .then([](B b){return C(b);})
813 * .then([](C c){return D(c);});
815 * To avoid the redundant error checking that would happen if a call at the
816 * front of the chain returns an error, these call chains can be collaped into
817 * a single call to .then:
819 * Expected<D, Error> maybeD = someFunc()
820 * .then([](A a){return B(a);},
821 * [](B b){return C(b);},
822 * [](C c){return D(c);});
824 * The result of .then() is wrapped into Expected< ~, Error > if it isn't
825 * of that form already. Consider the following code:
827 * extern Expected<std::string, Error> readLineFromIO();
828 * extern Expected<int, Error> parseInt(std::string);
829 * extern int increment(int);
831 * Expected<int, Error> x = readLineFromIO().then(parseInt).then(increment);
833 * From the code above, we see that .then() works both with functions that
834 * return an Expected< ~, Error > (like parseInt) and with ones that return
835 * a plain value (like increment). In the case of parseInt, .then() returns
836 * the result of parseInt as-is. In the case of increment, it wraps the int
837 * that increment returns into an Expected< int, Error >.
839 * Sometimes when using a continuation you would prefer an exception to be
840 * thrown for a value-less Expected. For that you can use .thenOrThrow, as
844 * .thenOrThrow([](A a){return B(a);});
846 * The above call to thenOrThrow will invoke the lambda if the Expected returned
847 * by someFunc() contains a value. Otherwise, it will throw an exception of type
848 * Unexpected<Error>::BadExpectedAccess. If you prefer it throw an exception of
849 * a different type, you can pass a second lambda to thenOrThrow:
852 * .thenOrThrow([](A a){return B(a);},
853 * [](Error e) {throw MyException(e);});
855 * Like C++17's std::variant, Expected offers the almost-never-empty guarantee;
856 * that is, an Expected<Value, Error> almost always contains either a Value or
857 * and Error. Partially-formed Expected objects occur when an assignment to
858 * an Expected object that would change the type of the contained object (Value-
859 * to-Error or vice versa) throws. Trying to access either the contained value
860 * or error object causes Expected to throw folly::BadExpectedAccess.
862 * Expected models OptionalPointee, so calling 'get_pointer(ex)' will return a
863 * pointer to nullptr if the 'ex' is in the error state, and a pointer to the
866 * Expected<int, Error> maybeInt = ...;
867 * if (int* v = get_pointer(maybeInt)) {
868 * cout << *v << endl;
871 template <class Value, class Error>
872 class Expected final : expected_detail::ExpectedStorage<Value, Error> {
873 template <class, class>
874 friend class Expected;
875 template <class, class, expected_detail::StorageType>
876 friend struct expected_detail::ExpectedStorage;
877 friend struct expected_detail::ExpectedHelper;
878 using Base = expected_detail::ExpectedStorage<Value, Error>;
879 using MakeBadExpectedAccess =
880 typename Unexpected<Error>::MakeBadExpectedAccess;
884 const Base& base() const& {
888 return std::move(*this);
892 using value_type = Value;
893 using error_type = Error;
894 using IsTriviallyCopyable = typename expected_detail::
895 StrictAllOf<IsTriviallyCopyable, Value, Error>::type;
898 using rebind = Expected<U, Error>;
901 !std::is_reference<Value>::value,
902 "Expected may not be used with reference types");
904 !std::is_abstract<Value>::value,
905 "Expected may not be used with abstract types");
910 template <class B = Base, class = decltype(B{})>
911 Expected() noexcept(noexcept(B{})) : Base{} {}
912 Expected(const Expected& that) = default;
913 Expected(Expected&& that) = default;
917 class E FOLLY_REQUIRES_TRAILING(
918 !std::is_same<Expected<V, E>, Expected>::value &&
919 std::is_constructible<Value, V&&>::value &&
920 std::is_constructible<Error, E&&>::value)>
921 Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} {
922 *this = std::move(that);
925 FOLLY_REQUIRES(std::is_copy_constructible<Value>::value)
926 constexpr /* implicit */ Expected(const Value& val) noexcept(
927 noexcept(Value(val)))
928 : Base{expected_detail::ValueTag{}, val} {}
930 FOLLY_REQUIRES(std::is_move_constructible<Value>::value)
931 constexpr /* implicit */ Expected(Value&& val) noexcept(
932 noexcept(Value(std::move(val))))
933 : Base{expected_detail::ValueTag{}, std::move(val)} {}
935 template <class T FOLLY_REQUIRES_TRAILING(
936 std::is_convertible<T, Value>::value &&
937 !std::is_convertible<T, Error>::value)>
938 constexpr /* implicit */ Expected(T&& val) noexcept(
939 noexcept(Value(static_cast<T&&>(val))))
940 : Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {}
942 template <class... Ts FOLLY_REQUIRES_TRAILING(
943 std::is_constructible<Value, Ts&&...>::value)>
944 explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
945 noexcept(Value(std::declval<Ts>()...)))
946 : Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {}
950 class... Ts FOLLY_REQUIRES_TRAILING(
951 std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
953 explicit constexpr Expected(
955 std::initializer_list<U> il,
956 Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
957 : Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {}
959 // If overload resolution selects one of these deleted functions, that
960 // means you need to use makeUnexpected
961 /* implicit */ Expected(const Error&) = delete;
962 /* implicit */ Expected(Error&&) = delete;
964 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
965 constexpr Expected(unexpected_t, const Error& err) noexcept(
966 noexcept(Error(err)))
967 : Base{expected_detail::ErrorTag{}, err} {}
969 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
970 constexpr Expected(unexpected_t, Error&& err) noexcept(
971 noexcept(Error(std::move(err))))
972 : Base{expected_detail::ErrorTag{}, std::move(err)} {}
974 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
975 constexpr /* implicit */ Expected(const Unexpected<Error>& err) noexcept(
976 noexcept(Error(err.error())))
977 : Base{expected_detail::ErrorTag{}, err.error()} {}
979 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
980 constexpr /* implicit */ Expected(Unexpected<Error>&& err) noexcept(
981 noexcept(Error(std::move(err.error()))))
982 : Base{expected_detail::ErrorTag{}, std::move(err.error())} {}
985 * Assignment operators
987 Expected& operator=(const Expected& that) = default;
988 Expected& operator=(Expected&& that) = default;
992 class E FOLLY_REQUIRES_TRAILING(
993 !std::is_same<Expected<V, E>, Expected>::value &&
994 expected_detail::IsConvertible<V&&, Value>::value &&
995 expected_detail::IsConvertible<E&&, Error>::value)>
996 Expected& operator=(Expected<V, E> that) {
997 this->assign(std::move(that));
1001 FOLLY_REQUIRES(expected_detail::IsCopyable<Value>::value)
1002 Expected& operator=(const Value& val) noexcept(
1003 expected_detail::IsNothrowCopyable<Value>::value) {
1004 this->assignValue(val);
1008 FOLLY_REQUIRES(expected_detail::IsMovable<Value>::value)
1009 Expected& operator=(Value&& val) noexcept(
1010 expected_detail::IsNothrowMovable<Value>::value) {
1011 this->assignValue(std::move(val));
1015 template <class T FOLLY_REQUIRES_TRAILING(
1016 std::is_convertible<T, Value>::value &&
1017 !std::is_convertible<T, Error>::value)>
1018 Expected& operator=(T&& val) {
1019 this->assignValue(static_cast<T&&>(val));
1023 FOLLY_REQUIRES(expected_detail::IsCopyable<Error>::value)
1024 Expected& operator=(const Unexpected<Error>& err) noexcept(
1025 expected_detail::IsNothrowCopyable<Error>::value) {
1026 this->assignError(err.error());
1030 FOLLY_REQUIRES(expected_detail::IsMovable<Error>::value)
1031 Expected& operator=(Unexpected<Error>&& err) noexcept(
1032 expected_detail::IsNothrowMovable<Error>::value) {
1033 this->assignError(std::move(err.error()));
1037 template <class... Ts FOLLY_REQUIRES_TRAILING(
1038 std::is_constructible<Value, Ts&&...>::value)>
1039 void emplace(Ts&&... ts) {
1040 this->assignValue(static_cast<Ts&&>(ts)...);
1046 void swap(Expected& that) noexcept(
1047 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1048 if (this->uninitializedByException() || that.uninitializedByException()) {
1049 throw BadExpectedAccess();
1054 swap(this->value_, that.value_);
1056 Error e(std::move(that.error_));
1057 that.assignValue(std::move(this->value_));
1058 this->assignError(std::move(e));
1062 swap(this->error_, that.error_);
1064 Error e(std::move(this->error_));
1065 this->assignValue(std::move(that.value_));
1066 that.assignError(std::move(e));
1071 // If overload resolution selects one of these deleted functions, that
1072 // means you need to use makeUnexpected
1073 /* implicit */ Expected& operator=(const Error&) = delete;
1074 /* implicit */ Expected& operator=(Error&&) = delete;
1077 * Relational Operators
1079 template <class Val, class Err>
1080 friend typename std::enable_if<IsEqualityComparable<Val>::value, bool>::type
1081 operator==(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1082 template <class Val, class Err>
1083 friend typename std::enable_if<IsLessThanComparable<Val>::value, bool>::type
1084 operator<(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1089 constexpr bool hasValue() const noexcept {
1090 return expected_detail::Which::eValue == this->which_;
1093 constexpr bool hasError() const noexcept {
1094 return expected_detail::Which::eError == this->which_;
1097 using Base::uninitializedByException;
1099 const Value& value() const& {
1101 return this->Base::value();
1106 return this->Base::value();
1109 Value&& value() && {
1111 return std::move(this->Base::value());
1114 const Error& error() const& {
1116 return this->Base::error();
1121 return this->Base::error();
1124 Error&& error() && {
1126 return std::move(this->Base::error());
1129 // Return a copy of the value if set, or a given default if not.
1131 Value value_or(U&& dflt) const& {
1132 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1133 return this->value_;
1135 return static_cast<U&&>(dflt);
1139 Value value_or(U&& dflt) && {
1140 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1141 return std::move(this->value_);
1143 return static_cast<U&&>(dflt);
1146 explicit constexpr operator bool() const noexcept {
1150 const Value& operator*() const& {
1151 return this->value();
1154 Value& operator*() & {
1155 return this->value();
1158 Value&& operator*() && {
1159 return std::move(this->value());
1162 const Value* operator->() const {
1163 return std::addressof(this->value());
1166 Value* operator->() {
1167 return std::addressof(this->value());
1170 const Value* get_pointer() const& noexcept {
1171 return hasValue() ? std::addressof(this->value_) : nullptr;
1174 Value* get_pointer() & noexcept {
1175 return hasValue() ? std::addressof(this->value_) : nullptr;
1178 Value* get_pointer() && = delete;
1183 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1184 auto then(Fns&&... fns) const& -> decltype(
1185 expected_detail::ExpectedHelper::then_(
1186 std::declval<const Base&>(),
1187 std::declval<Fns>()...)) {
1188 if (this->uninitializedByException()) {
1189 throw BadExpectedAccess();
1191 return expected_detail::ExpectedHelper::then_(
1192 base(), static_cast<Fns&&>(fns)...);
1195 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1196 auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1197 std::declval<Base&>(),
1198 std::declval<Fns>()...)) {
1199 if (this->uninitializedByException()) {
1200 throw BadExpectedAccess();
1202 return expected_detail::ExpectedHelper::then_(
1203 base(), static_cast<Fns&&>(fns)...);
1206 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1207 auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1208 std::declval<Base&&>(),
1209 std::declval<Fns>()...)) {
1210 if (this->uninitializedByException()) {
1211 throw BadExpectedAccess();
1213 return expected_detail::ExpectedHelper::then_(
1214 std::move(base()), static_cast<Fns&&>(fns)...);
1220 template <class Yes, class No = MakeBadExpectedAccess>
1221 auto thenOrThrow(Yes&& yes, No&& no = No{}) const& -> decltype(
1222 std::declval<Yes>()(std::declval<const Value&>())) {
1223 using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1224 if (this->uninitializedByException()) {
1225 throw BadExpectedAccess();
1227 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1228 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1231 template <class Yes, class No = MakeBadExpectedAccess>
1232 auto thenOrThrow(Yes&& yes, No&& no = No{}) & -> decltype(
1233 std::declval<Yes>()(std::declval<Value&>())) {
1234 using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1235 if (this->uninitializedByException()) {
1236 throw BadExpectedAccess();
1238 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1239 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1242 template <class Yes, class No = MakeBadExpectedAccess>
1243 auto thenOrThrow(Yes&& yes, No&& no = No{}) && -> decltype(
1244 std::declval<Yes>()(std::declval<Value&&>())) {
1245 using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1246 if (this->uninitializedByException()) {
1247 throw BadExpectedAccess();
1249 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1250 std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1254 void requireValue() const {
1255 if (UNLIKELY(!hasValue())) {
1256 if (LIKELY(hasError())) {
1257 throw typename Unexpected<Error>::BadExpectedAccess(this->error_);
1259 throw BadExpectedAccess();
1263 void requireError() const {
1264 if (UNLIKELY(!hasError())) {
1265 throw BadExpectedAccess();
1269 expected_detail::Which which() const noexcept {
1270 return this->which_;
1274 template <class Value, class Error>
1275 inline typename std::enable_if<IsEqualityComparable<Value>::value, bool>::type
1277 const Expected<Value, Error>& lhs,
1278 const Expected<Value, Error>& rhs) {
1279 if (UNLIKELY(lhs.which_ != rhs.which_)) {
1280 return UNLIKELY(lhs.uninitializedByException()) ? false
1281 : throw BadExpectedAccess();
1283 if (UNLIKELY(lhs.uninitializedByException())) {
1284 throw BadExpectedAccess();
1286 if (UNLIKELY(lhs.hasError())) {
1287 return true; // All error states are considered equal
1289 return lhs.value_ == rhs.value_;
1294 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Value>::value)>
1295 inline bool operator!=(
1296 const Expected<Value, Error>& lhs,
1297 const Expected<Value, Error>& rhs) {
1298 return !(rhs == lhs);
1301 template <class Value, class Error>
1302 inline typename std::enable_if<IsLessThanComparable<Value>::value, bool>::type
1304 const Expected<Value, Error>& lhs,
1305 const Expected<Value, Error>& rhs) {
1307 lhs.uninitializedByException() || rhs.uninitializedByException())) {
1308 throw BadExpectedAccess();
1310 if (UNLIKELY(lhs.hasError())) {
1311 return !rhs.hasError();
1313 if (UNLIKELY(rhs.hasError())) {
1316 return lhs.value_ < rhs.value_;
1321 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1322 inline bool operator<=(
1323 const Expected<Value, Error>& lhs,
1324 const Expected<Value, Error>& rhs) {
1325 return !(rhs < lhs);
1330 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1331 inline bool operator>(
1332 const Expected<Value, Error>& lhs,
1333 const Expected<Value, Error>& rhs) {
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 !(lhs < rhs);
1347 * swap Expected values
1349 template <class Error, class Value>
1350 void swap(Expected<Error, Value>& lhs, Expected<Value, Error>& rhs) noexcept(
1351 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1355 template <class Value, class Error>
1356 const Value* get_pointer(const Expected<Value, Error>& ex) noexcept {
1357 return ex.get_pointer();
1360 template <class Value, class Error>
1361 Value* get_pointer(Expected<Value, Error>& ex) noexcept {
1362 return ex.get_pointer();
1366 * For constructing an Expected object from a value, with the specified
1367 * Error type. Usage is as follows:
1369 * enum MyErrorCode { BAD_ERROR, WORSE_ERROR };
1370 * Expected<int, MyErrorCode> myAPI() {
1372 * return i ? makeExpected<MyErrorCode>(i) : makeUnexpected(BAD_ERROR);
1375 template <class Error, class Value>
1376 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
1378 return Expected<typename std::decay<Value>::type, Error>{
1379 in_place, static_cast<Value&&>(val)};
1382 // Suppress comparability of Optional<T> with T, despite implicit conversion.
1383 template <class Value, class Error>
1384 bool operator==(const Expected<Value, Error>&, const Value& other) = delete;
1385 template <class Value, class Error>
1386 bool operator!=(const Expected<Value, Error>&, const Value& other) = delete;
1387 template <class Value, class Error>
1388 bool operator<(const Expected<Value, Error>&, const Value& other) = delete;
1389 template <class Value, class Error>
1390 bool operator<=(const Expected<Value, Error>&, const Value& other) = delete;
1391 template <class Value, class Error>
1392 bool operator>=(const Expected<Value, Error>&, const Value& other) = delete;
1393 template <class Value, class Error>
1394 bool operator>(const Expected<Value, Error>&, const Value& other) = delete;
1395 template <class Value, class Error>
1396 bool operator==(const Value& other, const Expected<Value, Error>&) = delete;
1397 template <class Value, class Error>
1398 bool operator!=(const Value& other, const Expected<Value, Error>&) = delete;
1399 template <class Value, class Error>
1400 bool operator<(const Value& other, const Expected<Value, Error>&) = delete;
1401 template <class Value, class Error>
1402 bool operator<=(const Value& other, const Expected<Value, Error>&) = delete;
1403 template <class Value, class Error>
1404 bool operator>=(const Value& other, const Expected<Value, Error>&) = delete;
1405 template <class Value, class Error>
1406 bool operator>(const Value& other, const Expected<Value, Error>&) = delete;
1408 } // namespace folly
1410 #if defined(__GNUC__) && !defined(__clang__)
1411 #pragma GCC diagnostic pop
1414 #undef FOLLY_REQUIRES
1415 #undef FOLLY_REQUIRES_TRAILING