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))
465 switch (that.which_) {
467 this->assignValue(static_cast<Other&&>(that).value());
470 this->assignError(static_cast<Other&&>(that).error());
479 // For small (pointer-sized) trivial types, a struct is faster than a union.
480 template <class Value, class Error>
481 struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
482 using value_type = Value;
483 using error_type = Error;
488 constexpr ExpectedStorage() noexcept
489 : which_(Which::eError), error_{}, value_{} {}
490 explicit constexpr ExpectedStorage(EmptyTag) noexcept
491 : which_(Which::eEmpty), error_{}, value_{} {}
492 template <class... Vs>
493 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
494 noexcept(Value(static_cast<Vs&&>(vs)...)))
495 : which_(Which::eValue), error_{}, value_(static_cast<Vs&&>(vs)...) {}
496 template <class... Es>
497 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
498 noexcept(Error(static_cast<Es&&>(es)...)))
499 : which_(Which::eError), error_(static_cast<Es&&>(es)...), value_{} {}
500 void clear() noexcept {}
501 constexpr static bool uninitializedByException() noexcept {
504 template <class... Vs>
505 void assignValue(Vs&&... vs) {
506 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
507 which_ = Which::eValue;
509 template <class... Es>
510 void assignError(Es&&... es) {
511 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
512 which_ = Which::eError;
514 template <class Other>
515 void assign(Other&& that) {
516 switch (that.which_) {
518 this->assignValue(static_cast<Other&&>(that).value());
521 this->assignError(static_cast<Other&&>(that).error());
531 const Value& value() const& {
535 return std::move(value_);
537 // TODO (t17322426): remove when VS2015 support is deprecated
538 // VS2015 static analyzer incorrectly flags these as unreachable in certain
539 // circumstances. VS2017 does not have this problem on the same code.
541 FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code
545 const Error& error() const& {
549 return std::move(error_);
554 namespace expected_detail_ExpectedHelper {
555 // Tricky hack so that Expected::then can handle lambdas that return void
557 inline T&& operator,(T&& t, Unit) noexcept {
558 return static_cast<T&&>(t);
561 struct ExpectedHelper {
562 template <class Error, class T>
563 static constexpr Expected<T, Error> return_(T t) {
564 return folly::makeExpected<Error>(t);
569 class U FOLLY_REQUIRES_TRAILING(
570 expected_detail::IsConvertible<U&&, Error>::value)>
571 static constexpr Expected<T, Error> return_(Expected<T, U> t) {
575 template <class This>
576 static typename std::decay<This>::type then_(This&& ex) {
577 return static_cast<This&&>(ex);
581 // Don't warn about not using the overloaded comma operator.
582 FOLLY_MSVC_DISABLE_WARNING(4913)
587 class E = ExpectedErrorType<This>,
588 class T = ExpectedHelper>
589 static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
590 T::template return_<E>(
591 (std::declval<Fn>()(std::declval<This>().value()), unit)),
592 std::declval<Fns>()...)) {
593 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
595 T::template return_<E>(
596 // Uses the comma operator defined above IFF the lambda
598 (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
599 static_cast<Fns&&>(fns)...);
600 return makeUnexpected(static_cast<This&&>(ex).error());
607 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
608 class Err = decltype(std::declval<No>()(std::declval<This>().error()))
609 FOLLY_REQUIRES_TRAILING(!std::is_void<Err>::value)>
610 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
611 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
612 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
613 throw static_cast<No&&>(no)(static_cast<This&&>(ex).error());
620 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
621 class Err = decltype(std::declval<No>()(std::declval<This&>().error()))
622 FOLLY_REQUIRES_TRAILING(std::is_void<Err>::value)>
623 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
624 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
625 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
626 static_cast<No&&>(no)(ex.error());
627 throw typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess()(
628 static_cast<This&&>(ex).error());
633 /* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
635 struct UnexpectedTag {};
637 } // namespace expected_detail
640 expected_detail::UnexpectedTag (&)(expected_detail::UnexpectedTag);
642 inline expected_detail::UnexpectedTag unexpected(
643 expected_detail::UnexpectedTag = {}) {
648 * An exception type thrown by Expected on catastrophic logic errors.
650 class BadExpectedAccess : public std::logic_error {
652 BadExpectedAccess() : std::logic_error("bad Expected access") {}
656 * Unexpected - a helper type used to disambiguate the construction of
657 * Expected objects in the error state.
659 template <class Error>
660 class Unexpected final {
662 friend class Unexpected;
663 template <class V, class E>
664 friend class Expected;
665 friend struct expected_detail::ExpectedHelper;
669 * Unexpected::BadExpectedAccess - An exception type thrown by Expected
670 * when the user tries to access the nested value but the Expected object is
671 * actually storing an error code.
673 class BadExpectedAccess : public folly::BadExpectedAccess {
675 explicit BadExpectedAccess(Error err)
676 : folly::BadExpectedAccess{}, error_(std::move(err)) {}
678 * The error code that was held by the Expected object when the user
679 * erroneously requested the value.
681 Error error() const {
692 Unexpected() = default;
693 Unexpected(const Unexpected&) = default;
694 Unexpected(Unexpected&&) = default;
695 Unexpected& operator=(const Unexpected&) = default;
696 Unexpected& operator=(Unexpected&&) = default;
697 constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {}
698 constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {}
700 template <class Other FOLLY_REQUIRES_TRAILING(
701 std::is_constructible<Error, Other&&>::value)>
702 constexpr /* implicit */ Unexpected(Unexpected<Other> that)
703 : error_(std::move(that.error())) {}
708 template <class Other FOLLY_REQUIRES_TRAILING(
709 std::is_assignable<Error&, Other&&>::value)>
710 Unexpected& operator=(Unexpected<Other> that) {
711 error_ = std::move(that.error());
720 const Error& error() const& {
724 return std::move(error_);
728 struct MakeBadExpectedAccess {
730 BadExpectedAccess operator()(E&& err) const {
731 return BadExpectedAccess(static_cast<E&&>(err));
739 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
740 inline bool operator==(
741 const Unexpected<Error>& lhs,
742 const Unexpected<Error>& rhs) {
743 return lhs.error() == rhs.error();
747 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
748 inline bool operator!=(
749 const Unexpected<Error>& lhs,
750 const Unexpected<Error>& rhs) {
751 return !(lhs == rhs);
755 * For constructing an Unexpected object from an error code. Unexpected objects
756 * are implicitly convertible to Expected object in the error state. Usage is
759 * enum class MyErrorCode { BAD_ERROR, WORSE_ERROR };
760 * Expected<int, MyErrorCode> myAPI() {
762 * return i ? makeExpected<MyErrorCode>(i)
763 * : makeUnexpected(MyErrorCode::BAD_ERROR);
766 template <class Error>
767 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(
769 return Unexpected<typename std::decay<Error>::type>{
770 static_cast<Error&&>(err)};
774 * Expected - For holding a value or an error. Useful as an alternative to
775 * exceptions, for APIs where throwing on failure would be too expensive.
777 * Expected<Value, Error> is a variant over the types Value and Error.
779 * Expected does not offer support for references. Use
780 * Expected<std::reference_wrapper<T>, Error> if your API needs to return a
781 * reference or an error.
783 * Expected offers a continuation-based interface to reduce the boilerplate
784 * of checking error codes. The Expected::then member function takes a lambda
785 * that is to execute should the Expected object contain a value. The return
786 * value of the lambda is wrapped in an Expected and returned. If the lambda is
787 * not executed because the Expected contains an error, the error is returned
788 * immediately in a new Expected object.
790 * Expected<int, Error> funcTheFirst();
791 * Expected<std::string, Error> funcTheSecond() {
792 * return funcTheFirst().then([](int i) { return std::to_string(i); });
795 * The above line of code could more verbosely written as:
797 * Expected<std::string, Error> funcTheSecond() {
798 * if (auto ex = funcTheFirst()) {
799 * return std::to_string(*ex);
801 * return makeUnexpected(ex.error());
804 * Continuations can chain, like:
806 * Expected<D, Error> maybeD = someFunc()
807 * .then([](A a){return B(a);})
808 * .then([](B b){return C(b);})
809 * .then([](C c){return D(c);});
811 * To avoid the redundant error checking that would happen if a call at the
812 * front of the chain returns an error, these call chains can be collaped into
813 * a single call to .then:
815 * Expected<D, Error> maybeD = someFunc()
816 * .then([](A a){return B(a);},
817 * [](B b){return C(b);},
818 * [](C c){return D(c);});
820 * The result of .then() is wrapped into Expected< ~, Error > if it isn't
821 * of that form already. Consider the following code:
823 * extern Expected<std::string, Error> readLineFromIO();
824 * extern Expected<int, Error> parseInt(std::string);
825 * extern int increment(int);
827 * Expected<int, Error> x = readLineFromIO().then(parseInt).then(increment);
829 * From the code above, we see that .then() works both with functions that
830 * return an Expected< ~, Error > (like parseInt) and with ones that return
831 * a plain value (like increment). In the case of parseInt, .then() returns
832 * the result of parseInt as-is. In the case of increment, it wraps the int
833 * that increment returns into an Expected< int, Error >.
835 * Sometimes when using a continuation you would prefer an exception to be
836 * thrown for a value-less Expected. For that you can use .thenOrThrow, as
840 * .thenOrThrow([](A a){return B(a);});
842 * The above call to thenOrThrow will invoke the lambda if the Expected returned
843 * by someFunc() contains a value. Otherwise, it will throw an exception of type
844 * Unexpected<Error>::BadExpectedAccess. If you prefer it throw an exception of
845 * a different type, you can pass a second lambda to thenOrThrow:
848 * .thenOrThrow([](A a){return B(a);},
849 * [](Error e) {throw MyException(e);});
851 * Like C++17's std::variant, Expected offers the almost-never-empty guarantee;
852 * that is, an Expected<Value, Error> almost always contains either a Value or
853 * and Error. Partially-formed Expected objects occur when an assignment to
854 * an Expected object that would change the type of the contained object (Value-
855 * to-Error or vice versa) throws. Trying to access either the contained value
856 * or error object causes Expected to throw folly::BadExpectedAccess.
858 * Expected models OptionalPointee, so calling 'get_pointer(ex)' will return a
859 * pointer to nullptr if the 'ex' is in the error state, and a pointer to the
862 * Expected<int, Error> maybeInt = ...;
863 * if (int* v = get_pointer(maybeInt)) {
864 * cout << *v << endl;
867 template <class Value, class Error>
868 class Expected final : expected_detail::ExpectedStorage<Value, Error> {
869 template <class, class>
870 friend class Expected;
871 template <class, class, expected_detail::StorageType>
872 friend struct expected_detail::ExpectedStorage;
873 friend struct expected_detail::ExpectedHelper;
874 using Base = expected_detail::ExpectedStorage<Value, Error>;
875 using MakeBadExpectedAccess =
876 typename Unexpected<Error>::MakeBadExpectedAccess;
880 const Base& base() const& {
884 return std::move(*this);
888 using value_type = Value;
889 using error_type = Error;
890 using IsTriviallyCopyable = typename expected_detail::
891 StrictAllOf<IsTriviallyCopyable, Value, Error>::type;
894 using rebind = Expected<U, Error>;
897 !std::is_reference<Value>::value,
898 "Expected may not be used with reference types");
900 !std::is_abstract<Value>::value,
901 "Expected may not be used with abstract types");
906 template <class B = Base, class = decltype(B{})>
907 Expected() noexcept(noexcept(B{})) : Base{} {}
908 Expected(const Expected& that) = default;
909 Expected(Expected&& that) = default;
913 class E FOLLY_REQUIRES_TRAILING(
914 !std::is_same<Expected<V, E>, Expected>::value &&
915 std::is_constructible<Value, V&&>::value &&
916 std::is_constructible<Error, E&&>::value)>
917 Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} {
918 *this = std::move(that);
921 FOLLY_REQUIRES(std::is_copy_constructible<Value>::value)
922 constexpr /* implicit */ Expected(const Value& val) noexcept(
923 noexcept(Value(val)))
924 : Base{expected_detail::ValueTag{}, val} {}
926 FOLLY_REQUIRES(std::is_move_constructible<Value>::value)
927 constexpr /* implicit */ Expected(Value&& val) noexcept(
928 noexcept(Value(std::move(val))))
929 : Base{expected_detail::ValueTag{}, std::move(val)} {}
931 template <class T FOLLY_REQUIRES_TRAILING(
932 std::is_convertible<T, Value>::value &&
933 !std::is_convertible<T, Error>::value)>
934 constexpr /* implicit */ Expected(T&& val) noexcept(
935 noexcept(Value(static_cast<T&&>(val))))
936 : Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {}
938 template <class... Ts FOLLY_REQUIRES_TRAILING(
939 std::is_constructible<Value, Ts&&...>::value)>
940 explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
941 noexcept(Value(std::declval<Ts>()...)))
942 : Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {}
946 class... Ts FOLLY_REQUIRES_TRAILING(
947 std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
949 explicit constexpr Expected(
951 std::initializer_list<U> il,
952 Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
953 : Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {}
955 // If overload resolution selects one of these deleted functions, that
956 // means you need to use makeUnexpected
957 /* implicit */ Expected(const Error&) = delete;
958 /* implicit */ Expected(Error&&) = delete;
960 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
961 constexpr Expected(unexpected_t, const Error& err) noexcept(
962 noexcept(Error(err)))
963 : Base{expected_detail::ErrorTag{}, err} {}
965 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
966 constexpr Expected(unexpected_t, Error&& err) noexcept(
967 noexcept(Error(std::move(err))))
968 : Base{expected_detail::ErrorTag{}, std::move(err)} {}
970 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
971 constexpr /* implicit */ Expected(const Unexpected<Error>& err) noexcept(
972 noexcept(Error(err.error())))
973 : Base{expected_detail::ErrorTag{}, err.error()} {}
975 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
976 constexpr /* implicit */ Expected(Unexpected<Error>&& err) noexcept(
977 noexcept(Error(std::move(err.error()))))
978 : Base{expected_detail::ErrorTag{}, std::move(err.error())} {}
981 * Assignment operators
983 Expected& operator=(const Expected& that) = default;
984 Expected& operator=(Expected&& that) = default;
988 class E FOLLY_REQUIRES_TRAILING(
989 !std::is_same<Expected<V, E>, Expected>::value &&
990 expected_detail::IsConvertible<V&&, Value>::value &&
991 expected_detail::IsConvertible<E&&, Error>::value)>
992 Expected& operator=(Expected<V, E> that) {
993 this->assign(std::move(that));
997 FOLLY_REQUIRES(expected_detail::IsCopyable<Value>::value)
998 Expected& operator=(const Value& val) noexcept(
999 expected_detail::IsNothrowCopyable<Value>::value) {
1000 this->assignValue(val);
1004 FOLLY_REQUIRES(expected_detail::IsMovable<Value>::value)
1005 Expected& operator=(Value&& val) noexcept(
1006 expected_detail::IsNothrowMovable<Value>::value) {
1007 this->assignValue(std::move(val));
1011 template <class T FOLLY_REQUIRES_TRAILING(
1012 std::is_convertible<T, Value>::value &&
1013 !std::is_convertible<T, Error>::value)>
1014 Expected& operator=(T&& val) {
1015 this->assignValue(static_cast<T&&>(val));
1019 FOLLY_REQUIRES(expected_detail::IsCopyable<Error>::value)
1020 Expected& operator=(const Unexpected<Error>& err) noexcept(
1021 expected_detail::IsNothrowCopyable<Error>::value) {
1022 this->assignError(err.error());
1026 FOLLY_REQUIRES(expected_detail::IsMovable<Error>::value)
1027 Expected& operator=(Unexpected<Error>&& err) noexcept(
1028 expected_detail::IsNothrowMovable<Error>::value) {
1029 this->assignError(std::move(err.error()));
1033 template <class... Ts FOLLY_REQUIRES_TRAILING(
1034 std::is_constructible<Value, Ts&&...>::value)>
1035 void emplace(Ts&&... ts) {
1036 this->assignValue(static_cast<Ts&&>(ts)...);
1042 void swap(Expected& that) noexcept(
1043 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1044 if (this->uninitializedByException() || that.uninitializedByException())
1045 throw BadExpectedAccess();
1049 swap(this->value_, that.value_);
1051 Error e(std::move(that.error_));
1052 that.assignValue(std::move(this->value_));
1053 this->assignError(std::move(e));
1057 swap(this->error_, that.error_);
1059 Error e(std::move(this->error_));
1060 this->assignValue(std::move(that.value_));
1061 that.assignError(std::move(e));
1066 // If overload resolution selects one of these deleted functions, that
1067 // means you need to use makeUnexpected
1068 /* implicit */ Expected& operator=(const Error&) = delete;
1069 /* implicit */ Expected& operator=(Error&&) = delete;
1072 * Relational Operators
1074 template <class Val, class Err>
1075 friend typename std::enable_if<IsEqualityComparable<Val>::value, bool>::type
1076 operator==(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1077 template <class Val, class Err>
1078 friend typename std::enable_if<IsLessThanComparable<Val>::value, bool>::type
1079 operator<(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1084 constexpr bool hasValue() const noexcept {
1085 return expected_detail::Which::eValue == this->which_;
1088 constexpr bool hasError() const noexcept {
1089 return expected_detail::Which::eError == this->which_;
1092 using Base::uninitializedByException;
1094 const Value& value() const& {
1096 return this->Base::value();
1101 return this->Base::value();
1104 Value&& value() && {
1106 return std::move(this->Base::value());
1109 const Error& error() const& {
1111 return this->Base::error();
1116 return this->Base::error();
1119 Error&& error() && {
1121 return std::move(this->Base::error());
1124 // Return a copy of the value if set, or a given default if not.
1126 Value value_or(U&& dflt) const& {
1127 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1128 return this->value_;
1130 return static_cast<U&&>(dflt);
1134 Value value_or(U&& dflt) && {
1135 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1136 return std::move(this->value_);
1138 return static_cast<U&&>(dflt);
1141 explicit constexpr operator bool() const noexcept {
1145 const Value& operator*() const& {
1146 return this->value();
1149 Value& operator*() & {
1150 return this->value();
1153 Value&& operator*() && {
1154 return std::move(this->value());
1157 const Value* operator->() const {
1158 return std::addressof(this->value());
1161 Value* operator->() {
1162 return std::addressof(this->value());
1165 const Value* get_pointer() const& noexcept {
1166 return hasValue() ? std::addressof(this->value_) : nullptr;
1169 Value* get_pointer() & noexcept {
1170 return hasValue() ? std::addressof(this->value_) : nullptr;
1173 Value* get_pointer() && = delete;
1178 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1179 auto then(Fns&&... fns) const& -> decltype(
1180 expected_detail::ExpectedHelper::then_(
1181 std::declval<const Base&>(),
1182 std::declval<Fns>()...)) {
1183 if (this->uninitializedByException())
1184 throw BadExpectedAccess();
1185 return expected_detail::ExpectedHelper::then_(
1186 base(), static_cast<Fns&&>(fns)...);
1189 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1190 auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1191 std::declval<Base&>(),
1192 std::declval<Fns>()...)) {
1193 if (this->uninitializedByException())
1194 throw BadExpectedAccess();
1195 return expected_detail::ExpectedHelper::then_(
1196 base(), static_cast<Fns&&>(fns)...);
1199 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1200 auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1201 std::declval<Base&&>(),
1202 std::declval<Fns>()...)) {
1203 if (this->uninitializedByException())
1204 throw BadExpectedAccess();
1205 return expected_detail::ExpectedHelper::then_(
1206 std::move(base()), static_cast<Fns&&>(fns)...);
1212 template <class Yes, class No = MakeBadExpectedAccess>
1213 auto thenOrThrow(Yes&& yes, No&& no = No{}) const& -> decltype(
1214 std::declval<Yes>()(std::declval<const Value&>())) {
1215 using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1216 if (this->uninitializedByException())
1217 throw BadExpectedAccess();
1218 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1219 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1222 template <class Yes, class No = MakeBadExpectedAccess>
1223 auto thenOrThrow(Yes&& yes, No&& no = No{}) & -> decltype(
1224 std::declval<Yes>()(std::declval<Value&>())) {
1225 using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1226 if (this->uninitializedByException())
1227 throw BadExpectedAccess();
1228 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1229 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1232 template <class Yes, class No = MakeBadExpectedAccess>
1233 auto thenOrThrow(Yes&& yes, No&& no = No{}) && -> decltype(
1234 std::declval<Yes>()(std::declval<Value&&>())) {
1235 using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1236 if (this->uninitializedByException())
1237 throw BadExpectedAccess();
1238 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1239 std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1243 void requireValue() const {
1244 if (UNLIKELY(!hasValue())) {
1245 if (LIKELY(hasError()))
1246 throw typename Unexpected<Error>::BadExpectedAccess(this->error_);
1247 throw BadExpectedAccess();
1251 void requireError() const {
1252 if (UNLIKELY(!hasError())) {
1253 throw BadExpectedAccess();
1257 expected_detail::Which which() const noexcept {
1258 return this->which_;
1262 template <class Value, class Error>
1263 inline typename std::enable_if<IsEqualityComparable<Value>::value, bool>::type
1265 const Expected<Value, Error>& lhs,
1266 const Expected<Value, Error>& rhs) {
1267 if (UNLIKELY(lhs.which_ != rhs.which_))
1268 return UNLIKELY(lhs.uninitializedByException()) ? false
1269 : throw BadExpectedAccess();
1270 if (UNLIKELY(lhs.uninitializedByException()))
1271 throw BadExpectedAccess();
1272 if (UNLIKELY(lhs.hasError()))
1273 return true; // All error states are considered equal
1274 return lhs.value_ == rhs.value_;
1279 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Value>::value)>
1280 inline bool operator!=(
1281 const Expected<Value, Error>& lhs,
1282 const Expected<Value, Error>& rhs) {
1283 return !(rhs == lhs);
1286 template <class Value, class Error>
1287 inline typename std::enable_if<IsLessThanComparable<Value>::value, bool>::type
1289 const Expected<Value, Error>& lhs,
1290 const Expected<Value, Error>& rhs) {
1292 lhs.uninitializedByException() || rhs.uninitializedByException()))
1293 throw BadExpectedAccess();
1294 if (UNLIKELY(lhs.hasError()))
1295 return !rhs.hasError();
1296 if (UNLIKELY(rhs.hasError()))
1298 return lhs.value_ < rhs.value_;
1303 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1304 inline bool operator<=(
1305 const Expected<Value, Error>& lhs,
1306 const Expected<Value, Error>& rhs) {
1307 return !(rhs < lhs);
1312 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1313 inline bool operator>(
1314 const Expected<Value, Error>& lhs,
1315 const Expected<Value, Error>& rhs) {
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 !(lhs < rhs);
1329 * swap Expected values
1331 template <class Error, class Value>
1332 void swap(Expected<Error, Value>& lhs, Expected<Value, Error>& rhs) noexcept(
1333 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1337 template <class Value, class Error>
1338 const Value* get_pointer(const Expected<Value, Error>& ex) noexcept {
1339 return ex.get_pointer();
1342 template <class Value, class Error>
1343 Value* get_pointer(Expected<Value, Error>& ex) noexcept {
1344 return ex.get_pointer();
1348 * For constructing an Expected object from a value, with the specified
1349 * Error type. Usage is as follows:
1351 * enum MyErrorCode { BAD_ERROR, WORSE_ERROR };
1352 * Expected<int, MyErrorCode> myAPI() {
1354 * return i ? makeExpected<MyErrorCode>(i) : makeUnexpected(BAD_ERROR);
1357 template <class Error, class Value>
1358 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
1360 return Expected<typename std::decay<Value>::type, Error>{
1361 in_place, static_cast<Value&&>(val)};
1364 // Suppress comparability of Optional<T> with T, despite implicit conversion.
1365 template <class Value, class Error>
1366 bool operator==(const Expected<Value, Error>&, const Value& other) = delete;
1367 template <class Value, class Error>
1368 bool operator!=(const Expected<Value, Error>&, const Value& other) = delete;
1369 template <class Value, class Error>
1370 bool operator<(const Expected<Value, Error>&, const Value& other) = delete;
1371 template <class Value, class Error>
1372 bool operator<=(const Expected<Value, Error>&, const Value& other) = delete;
1373 template <class Value, class Error>
1374 bool operator>=(const Expected<Value, Error>&, const Value& other) = delete;
1375 template <class Value, class Error>
1376 bool operator>(const Expected<Value, Error>&, const Value& other) = delete;
1377 template <class Value, class Error>
1378 bool operator==(const Value& other, const Expected<Value, Error>&) = delete;
1379 template <class Value, class Error>
1380 bool operator!=(const Value& other, const Expected<Value, Error>&) = delete;
1381 template <class Value, class Error>
1382 bool operator<(const Value& other, const Expected<Value, Error>&) = delete;
1383 template <class Value, class Error>
1384 bool operator<=(const Value& other, const Expected<Value, Error>&) = delete;
1385 template <class Value, class Error>
1386 bool operator>=(const Value& other, const Expected<Value, Error>&) = delete;
1387 template <class Value, class Error>
1388 bool operator>(const Value& other, const Expected<Value, Error>&) = delete;
1390 } // namespace folly
1392 #if defined(__GNUC__) && !defined(__clang__)
1393 #pragma GCC diagnostic pop
1396 #undef FOLLY_REQUIRES
1397 #undef FOLLY_REQUIRES_TRAILING