2 * Copyright 2016 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* and 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> // for construct_in_place_t
36 #include <folly/Unit.h>
38 #define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__)
40 #define FOLLY_REQUIRES_IMPL(...) \
41 bool FOLLY_EXPECTED_ID(Requires) = false, \
42 typename std::enable_if< \
43 (FOLLY_EXPECTED_ID(Requires) || static_cast<bool>(__VA_ARGS__)), \
46 #define FOLLY_REQUIRES_TRAILING(...) , FOLLY_REQUIRES_IMPL(__VA_ARGS__)
48 #define FOLLY_REQUIRES(...) template <FOLLY_REQUIRES_IMPL(__VA_ARGS__)>
51 * gcc-4.7 warns about use of uninitialized memory around the use of storage_
52 * even though this is explicitly initialized at each point.
54 #if defined(__GNUC__) && !defined(__clang__)
55 #pragma GCC diagnostic push
56 #pragma GCC diagnostic ignored "-Wuninitialized"
57 #pragma GCC diagnostic ignored "-Wpragmas"
58 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
64 * Forward declarations
66 template <class Error>
69 template <class Error>
70 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(Error&&);
72 template <class Value, class Error>
75 template <class Error, class Value>
76 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
80 * Alias for an Expected type's assiciated value_type
82 template <class Expected>
83 using ExpectedValueType =
84 typename std::remove_reference<Expected>::type::value_type;
87 * Alias for an Expected type's assiciated error_type
89 template <class Expected>
90 using ExpectedErrorType =
91 typename std::remove_reference<Expected>::type::error_type;
94 namespace expected_detail {
96 // MSVC 2015 can't handle the StrictConjunction, so we have
97 // to use std::conjunction instead.
98 template <template <class...> class Trait, class... Ts>
99 using StrictAllOf = std::conjunction<Trait<Ts>...>;
101 template <template <class...> class Trait, class... Ts>
102 using StrictAllOf = StrictConjunction<Trait<Ts>...>;
106 using IsCopyable = StrictConjunction<
107 std::is_copy_constructible<T>,
108 std::is_copy_assignable<T>>;
111 using IsMovable = StrictConjunction<
112 std::is_move_constructible<T>,
113 std::is_move_assignable<T>>;
116 using IsNothrowCopyable = StrictConjunction<
117 std::is_nothrow_copy_constructible<T>,
118 std::is_nothrow_copy_assignable<T>>;
121 using IsNothrowMovable = StrictConjunction<
122 std::is_nothrow_move_constructible<T>,
123 std::is_nothrow_move_assignable<T>>;
125 template <class From, class To>
126 using IsConvertible = StrictConjunction<
127 std::is_constructible<To, From>,
128 std::is_assignable<To&, From>>;
130 template <class T, class U>
131 auto doEmplaceAssign(int, T& t, U&& u) -> decltype(void(t = (U &&)u)) {
135 template <class T, class U>
136 auto doEmplaceAssign(long, T& t, U&& u) -> decltype(void(T((U &&)u))) {
138 ::new ((void*)std::addressof(t)) T((U &&)u);
141 template <class T, class... Us>
142 auto doEmplaceAssign(int, T& t, Us&&... us)
143 -> decltype(void(t = T((Us &&)us...))) {
147 template <class T, class... Us>
148 auto doEmplaceAssign(long, T& t, Us&&... us)
149 -> decltype(void(T((Us &&)us...))) {
151 ::new ((void*)std::addressof(t)) T((Us &&)us...);
157 enum class Which : unsigned char { eEmpty, eValue, eError };
158 enum class StorageType { ePODStruct, ePODUnion, eUnion };
160 template <class Value, class Error>
161 constexpr StorageType getStorageType() {
162 return StrictAllOf<IsTriviallyCopyable, Value, Error>::value
163 ? (sizeof(std::pair<Value, Error>) <= sizeof(void * [2]) &&
164 StrictAllOf<std::is_trivial, Value, Error>::value
165 ? StorageType::ePODStruct
166 : StorageType::ePODUnion)
167 : StorageType::eUnion;
173 StorageType = expected_detail::getStorageType<Value, Error>()> // ePODUnion
174 struct ExpectedStorage {
175 using value_type = Value;
176 using error_type = Error;
184 template <class E = Error, class = decltype(E{})>
185 constexpr ExpectedStorage() noexcept(noexcept(E{}))
186 : error_{}, which_(Which::eError) {}
187 explicit constexpr ExpectedStorage(EmptyTag) noexcept
188 : ch_{}, which_(Which::eEmpty) {}
189 template <class... Vs>
190 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
191 noexcept(Value(static_cast<Vs&&>(vs)...)))
192 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
193 template <class... Es>
194 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
195 noexcept(Error(static_cast<Es&&>(es)...)))
196 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
197 void clear() noexcept {}
198 static constexpr bool uninitializedByException() noexcept {
199 // Although which_ may temporarily be eEmpty during construction, it
200 // is always either eValue or eError for a fully-constructed Expected.
203 template <class... Vs>
204 void assignValue(Vs&&... vs) {
205 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
206 which_ = Which::eValue;
208 template <class... Es>
209 void assignError(Es&&... es) {
210 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
211 which_ = Which::eError;
213 template <class Other>
214 void assign(Other&& that) {
215 switch (that.which_) {
217 this->assignValue(static_cast<Other&&>(that).value());
220 this->assignError(static_cast<Other&&>(that).error());
230 const Value& value() const& {
234 return std::move(value_);
239 const Error& error() const& {
243 return std::move(error_);
247 template <class Value, class Error>
248 struct ExpectedUnion {
254 Which which_ = Which::eEmpty;
256 explicit constexpr ExpectedUnion(EmptyTag) noexcept {}
257 template <class... Vs>
258 explicit constexpr ExpectedUnion(ValueTag, Vs&&... vs) noexcept(
259 noexcept(Value(static_cast<Vs&&>(vs)...)))
260 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
261 template <class... Es>
262 explicit constexpr ExpectedUnion(ErrorTag, Es&&... es) noexcept(
263 noexcept(Error(static_cast<Es&&>(es)...)))
264 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
265 ExpectedUnion(const ExpectedUnion&) {}
266 ExpectedUnion(ExpectedUnion&&) noexcept {}
267 ExpectedUnion& operator=(const ExpectedUnion&) {
270 ExpectedUnion& operator=(ExpectedUnion&&) noexcept {
277 const Value& value() const& {
281 return std::move(value_);
286 const Error& error() const& {
290 return std::move(error_);
294 template <class Derived, bool, bool Noexcept>
295 struct CopyConstructible {
296 constexpr CopyConstructible() = default;
297 CopyConstructible(const CopyConstructible& that) noexcept(Noexcept) {
298 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
300 constexpr CopyConstructible(CopyConstructible&&) = default;
301 CopyConstructible& operator=(const CopyConstructible&) = default;
302 CopyConstructible& operator=(CopyConstructible&&) = default;
305 template <class Derived, bool Noexcept>
306 struct CopyConstructible<Derived, false, Noexcept> {
307 constexpr CopyConstructible() = default;
308 CopyConstructible(const CopyConstructible&) = delete;
309 constexpr CopyConstructible(CopyConstructible&&) = default;
310 CopyConstructible& operator=(const CopyConstructible&) = default;
311 CopyConstructible& operator=(CopyConstructible&&) = default;
314 template <class Derived, bool, bool Noexcept>
315 struct MoveConstructible {
316 constexpr MoveConstructible() = default;
317 constexpr MoveConstructible(const MoveConstructible&) = default;
318 MoveConstructible(MoveConstructible&& that) noexcept(Noexcept) {
319 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
321 MoveConstructible& operator=(const MoveConstructible&) = default;
322 MoveConstructible& operator=(MoveConstructible&&) = default;
325 template <class Derived, bool Noexcept>
326 struct MoveConstructible<Derived, false, Noexcept> {
327 constexpr MoveConstructible() = default;
328 constexpr MoveConstructible(const MoveConstructible&) = default;
329 MoveConstructible(MoveConstructible&&) = delete;
330 MoveConstructible& operator=(const MoveConstructible&) = default;
331 MoveConstructible& operator=(MoveConstructible&&) = default;
334 template <class Derived, bool, bool Noexcept>
335 struct CopyAssignable {
336 constexpr CopyAssignable() = default;
337 constexpr CopyAssignable(const CopyAssignable&) = default;
338 constexpr CopyAssignable(CopyAssignable&&) = default;
339 CopyAssignable& operator=(const CopyAssignable& that) noexcept(Noexcept) {
340 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
343 CopyAssignable& operator=(CopyAssignable&&) = default;
346 template <class Derived, bool Noexcept>
347 struct CopyAssignable<Derived, false, Noexcept> {
348 constexpr CopyAssignable() = default;
349 constexpr CopyAssignable(const CopyAssignable&) = default;
350 constexpr CopyAssignable(CopyAssignable&&) = default;
351 CopyAssignable& operator=(const CopyAssignable&) = delete;
352 CopyAssignable& operator=(CopyAssignable&&) = default;
355 template <class Derived, bool, bool Noexcept>
356 struct MoveAssignable {
357 constexpr MoveAssignable() = default;
358 constexpr MoveAssignable(const MoveAssignable&) = default;
359 constexpr MoveAssignable(MoveAssignable&&) = default;
360 MoveAssignable& operator=(const MoveAssignable&) = default;
361 MoveAssignable& operator=(MoveAssignable&& that) noexcept(Noexcept) {
362 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
367 template <class Derived, bool Noexcept>
368 struct MoveAssignable<Derived, false, Noexcept> {
369 constexpr MoveAssignable() = default;
370 constexpr MoveAssignable(const MoveAssignable&) = default;
371 constexpr MoveAssignable(MoveAssignable&&) = default;
372 MoveAssignable& operator=(const MoveAssignable&) = default;
373 MoveAssignable& operator=(MoveAssignable&& that) = delete;
376 template <class Value, class Error>
377 struct ExpectedStorage<Value, Error, StorageType::eUnion>
378 : ExpectedUnion<Value, Error>,
380 ExpectedStorage<Value, Error, StorageType::eUnion>,
381 StrictAllOf<std::is_copy_constructible, Value, Error>::value,
382 StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::value>,
384 ExpectedStorage<Value, Error, StorageType::eUnion>,
385 StrictAllOf<std::is_move_constructible, Value, Error>::value,
386 StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::value>,
388 ExpectedStorage<Value, Error, StorageType::eUnion>,
389 StrictAllOf<IsCopyable, Value, Error>::value,
390 StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
392 ExpectedStorage<Value, Error, StorageType::eUnion>,
393 StrictAllOf<IsMovable, Value, Error>::value,
394 StrictAllOf<IsNothrowMovable, Value, Error>::value> {
395 using value_type = Value;
396 using error_type = Error;
397 using Base = ExpectedUnion<Value, Error>;
398 template <class E = Error, class = decltype(E{})>
399 constexpr ExpectedStorage() noexcept(noexcept(E{})) : Base{ErrorTag{}} {}
400 ExpectedStorage(const ExpectedStorage&) = default;
401 ExpectedStorage(ExpectedStorage&&) = default;
402 ExpectedStorage& operator=(const ExpectedStorage&) = default;
403 ExpectedStorage& operator=(ExpectedStorage&&) = default;
404 using ExpectedUnion<Value, Error>::ExpectedUnion;
408 void clear() noexcept {
409 switch (this->which_) {
411 this->value().~Value();
414 this->error().~Error();
419 this->which_ = Which::eEmpty;
421 bool uninitializedByException() const noexcept {
422 return this->which_ == Which::eEmpty;
424 template <class... Vs>
425 void assignValue(Vs&&... vs) {
426 if (this->which_ == Which::eValue) {
427 expected_detail::doEmplaceAssign(
428 0, this->value(), static_cast<Vs&&>(vs)...);
431 ::new ((void*)std::addressof(this->value()))
432 Value(static_cast<Vs&&>(vs)...);
433 this->which_ = Which::eValue;
436 template <class... Es>
437 void assignError(Es&&... es) {
438 if (this->which_ == Which::eError) {
439 expected_detail::doEmplaceAssign(
440 0, this->error(), static_cast<Es&&>(es)...);
443 ::new ((void*)std::addressof(this->error()))
444 Error(static_cast<Es&&>(es)...);
445 this->which_ = Which::eError;
448 bool isThis(const ExpectedStorage* that) const {
451 constexpr bool isSelfAssign(const void*) const {
454 template <class Other>
455 void assign(Other&& that) {
456 if (isSelfAssign(&that))
458 switch (that.which_) {
460 this->assignValue(static_cast<Other&&>(that).value());
463 this->assignError(static_cast<Other&&>(that).error());
472 // For small (pointer-sized) trivial types, a struct is faster than a union.
473 template <class Value, class Error>
474 struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
475 using value_type = Value;
476 using error_type = Error;
481 constexpr ExpectedStorage() noexcept
482 : which_(Which::eError), error_{}, value_{} {}
483 explicit constexpr ExpectedStorage(EmptyTag) noexcept
484 : which_(Which::eEmpty), error_{}, value_{} {}
485 template <class... Vs>
486 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
487 noexcept(Value(static_cast<Vs&&>(vs)...)))
488 : which_(Which::eValue), error_{}, value_(static_cast<Vs&&>(vs)...) {}
489 template <class... Es>
490 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
491 noexcept(Error(static_cast<Es&&>(es)...)))
492 : which_(Which::eError), error_(static_cast<Es&&>(es)...), value_{} {}
493 void clear() noexcept {}
494 constexpr static bool uninitializedByException() noexcept {
497 template <class... Vs>
498 void assignValue(Vs&&... vs) {
499 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
500 which_ = Which::eValue;
502 template <class... Es>
503 void assignError(Es&&... es) {
504 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
505 which_ = Which::eError;
507 template <class Other>
508 void assign(Other&& that) {
509 switch (that.which_) {
511 this->assignValue(static_cast<Other&&>(that).value());
514 this->assignError(static_cast<Other&&>(that).error());
524 const Value& value() const& {
528 return std::move(value_);
533 const Error& error() const& {
537 return std::move(error_);
541 namespace expected_detail_ExpectedHelper {
542 // Tricky hack so that Expected::then can handle lambdas that return void
544 inline T&& operator,(T&& t, Unit) noexcept {
545 return static_cast<T&&>(t);
548 struct ExpectedHelper {
549 template <class Error, class T>
550 static constexpr Expected<T, Error> return_(T t) {
551 return folly::makeExpected<Error>(t);
556 class U FOLLY_REQUIRES_TRAILING(
557 expected_detail::IsConvertible<U&&, Error>::value)>
558 static constexpr Expected<T, Error> return_(Expected<T, U> t) {
562 template <class This>
563 static typename std::decay<This>::type then_(This&& ex) {
564 return static_cast<This&&>(ex);
568 // Don't warn about not using the overloaded comma operator.
569 FOLLY_MSVC_DISABLE_WARNING(4913)
574 class E = ExpectedErrorType<This>,
575 class T = ExpectedHelper>
576 static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
577 T::template return_<E>(
578 (std::declval<Fn>()(std::declval<This>().value()), unit)),
579 std::declval<Fns>()...)) {
580 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
582 T::template return_<E>(
583 // Uses the comma operator defined above IFF the lambda
585 (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
586 static_cast<Fns&&>(fns)...);
587 return makeUnexpected(static_cast<This&&>(ex).error());
594 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
595 class Err = decltype(std::declval<No>()(std::declval<This>().error()))
596 FOLLY_REQUIRES_TRAILING(!std::is_void<Err>::value)>
597 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
598 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
599 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
600 throw static_cast<No&&>(no)(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 static_cast<No&&>(no)(ex.error());
614 throw typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess()(
615 static_cast<This&&>(ex).error());
620 /* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
622 struct UnexpectedTag {};
624 } // namespace expected_detail
627 expected_detail::UnexpectedTag (&)(expected_detail::UnexpectedTag);
629 inline expected_detail::UnexpectedTag unexpected(
630 expected_detail::UnexpectedTag = {}) {
635 * An exception type thrown by Expected on catastrophic logic errors.
637 class BadExpectedAccess : public std::logic_error {
639 BadExpectedAccess() : std::logic_error("bad Expected access") {}
643 * Unexpected - a helper type used to disambiguate the construction of
644 * Expected objects in the error state.
646 template <class Error>
647 class Unexpected final {
649 friend class Unexpected;
650 template <class V, class E>
651 friend class Expected;
652 friend struct expected_detail::ExpectedHelper;
656 * Unexpected::BadExpectedAccess - An exception type thrown by Expected
657 * when the user tries to access the nested value but the Expected object is
658 * actually storing an error code.
660 class BadExpectedAccess : public folly::BadExpectedAccess {
662 explicit BadExpectedAccess(Error err)
663 : folly::BadExpectedAccess{}, error_(std::move(err)) {}
665 * The error code that was held by the Expected object when the user
666 * erroneously requested the value.
668 Error error() const {
679 Unexpected() = default;
680 Unexpected(const Unexpected&) = default;
681 Unexpected(Unexpected&&) = default;
682 Unexpected& operator=(const Unexpected&) = default;
683 Unexpected& operator=(Unexpected&&) = default;
684 constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {}
685 constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {}
687 template <class Other FOLLY_REQUIRES_TRAILING(
688 std::is_constructible<Error, Other&&>::value)>
689 constexpr /* implicit */ Unexpected(Unexpected<Other> that)
690 : error_(std::move(that.error())) {}
695 template <class Other FOLLY_REQUIRES_TRAILING(
696 std::is_assignable<Error&, Other&&>::value)>
697 Unexpected& operator=(Unexpected<Other> that) {
698 error_ = std::move(that.error());
707 const Error& error() const& {
711 return std::move(error_);
715 struct MakeBadExpectedAccess {
717 BadExpectedAccess operator()(E&& err) const {
718 return BadExpectedAccess(static_cast<E&&>(err));
726 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
727 inline bool operator==(
728 const Unexpected<Error>& lhs,
729 const Unexpected<Error>& rhs) {
730 return lhs.error() == rhs.error();
734 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
735 inline bool operator!=(
736 const Unexpected<Error>& lhs,
737 const Unexpected<Error>& rhs) {
738 return !(lhs == rhs);
742 * For constructing an Unexpected object from an error code. Unexpected objects
743 * are implicitly convertible to Expected object in the error state. Usage is
746 * enum class MyErrorCode { BAD_ERROR, WORSE_ERROR };
747 * Expected<int, MyErrorCode> myAPI() {
749 * return i ? makeExpected<MyErrorCode>(i)
750 * : makeUnexpected(MyErrorCode::BAD_ERROR);
753 template <class Error>
754 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(
756 return Unexpected<typename std::decay<Error>::type>{
757 static_cast<Error&&>(err)};
761 * Expected - For holding a value or an error. Useful as an alternative to
762 * exceptions, for APIs where throwing on failure would be too expensive.
764 * Expected<Value, Error> is a variant over the types Value and Error.
766 * Expected does not offer support for references. Use
767 * Expected<std::reference_wrapper<T>, Error> if your API needs to return a
768 * reference or an error.
770 * Expected offers a continuation-based interface to reduce the boilerplate
771 * of checking error codes. The Expected::then member function takes a lambda
772 * that is to execute should the Expected object contain a value. The return
773 * value of the lambda is wrapped in an Expected and returned. If the lambda is
774 * not executed because the Expected contains an error, the error is returned
775 * immediately in a new Expected object.
777 * Expected<int, Error> funcTheFirst();
778 * Expected<std::string, Error> funcTheSecond() {
779 * return funcTheFirst().then([](int i) { return std::to_string(i); });
782 * The above line of code could more verbosely written as:
784 * Expected<std::string, Error> funcTheSecond() {
785 * if (auto ex = funcTheFirst()) {
786 * return std::to_string(*ex);
788 * return makeUnexpected(ex.error());
791 * Continuations can chain, like:
793 * Expected<D, Error> maybeD = someFunc()
794 * .then([](A a){return B(a);})
795 * .then([](B b){return C(b);})
796 * .then([](C c){return D(c);});
798 * To avoid the redundant error checking that would happen if a call at the
799 * front of the chain returns an error, these call chains can be collaped into
800 * a single call to .then:
802 * Expected<D, Error> maybeD = someFunc()
803 * .then([](A a){return B(a);},
804 * [](B b){return C(b);},
805 * [](C c){return D(c);});
807 * The result of .then() is wrapped into Expected< ~, Error > if it isn't
808 * of that form already. Consider the following code:
810 * extern Expected<std::string, Error> readLineFromIO();
811 * extern Expected<int, Error> parseInt(std::string);
812 * extern int increment(int);
814 * Expected<int, Error> x = readLineFromIO().then(parseInt).then(increment);
816 * From the code above, we see that .then() works both with functions that
817 * return an Expected< ~, Error > (like parseInt) and with ones that return
818 * a plain value (like increment). In the case of parseInt, .then() returns
819 * the result of parseInt as-is. In the case of increment, it wraps the int
820 * that increment returns into an Expected< int, Error >.
822 * Sometimes when using a continuation you would prefer an exception to be
823 * thrown for a value-less Expected. For that you can use .thenOrThrow, as
827 * .thenOrThrow([](A a){return B(a);});
829 * The above call to thenOrThrow will invoke the lambda if the Expected returned
830 * by someFunc() contains a value. Otherwise, it will throw an exception of type
831 * Unexpected<Error>::BadExpectedAccess. If you prefer it throw an exception of
832 * a different type, you can pass a second lambda to thenOrThrow:
835 * .thenOrThrow([](A a){return B(a);},
836 * [](Error e) {throw MyException(e);});
838 * Like C++17's std::variant, Expected offers the almost-never-empty guarantee;
839 * that is, an Expected<Value, Error> almost always contains either a Value or
840 * and Error. Partially-formed Expected objects occur when an assignment to
841 * an Expected object that would change the type of the contained object (Value-
842 * to-Error or vice versa) throws. Trying to access either the contained value
843 * or error object causes Expected to throw folly::BadExpectedAccess.
845 * Expected models OptionalPointee, so calling 'get_pointer(ex)' will return a
846 * pointer to nullptr if the 'ex' is in the error state, and a pointer to the
849 * Expected<int, Error> maybeInt = ...;
850 * if (int* v = get_pointer(maybeInt)) {
851 * cout << *v << endl;
854 template <class Value, class Error>
855 class Expected final : expected_detail::ExpectedStorage<Value, Error> {
856 template <class, class>
857 friend class Expected;
858 template <class, class, expected_detail::StorageType>
859 friend struct expected_detail::ExpectedStorage;
860 friend struct expected_detail::ExpectedHelper;
861 using Base = expected_detail::ExpectedStorage<Value, Error>;
862 using MakeBadExpectedAccess =
863 typename Unexpected<Error>::MakeBadExpectedAccess;
867 const Base& base() const& {
871 return std::move(*this);
875 using value_type = Value;
876 using error_type = Error;
877 using IsTriviallyCopyable = typename expected_detail::
878 StrictAllOf<IsTriviallyCopyable, Value, Error>::type;
881 using rebind = Expected<U, Error>;
884 !std::is_reference<Value>::value,
885 "Expected may not be used with reference types");
887 !std::is_abstract<Value>::value,
888 "Expected may not be used with abstract types");
893 template <class B = Base, class = decltype(B{})>
894 Expected() noexcept(noexcept(B{})) : Base{} {}
895 Expected(const Expected& that) = default;
896 Expected(Expected&& that) = default;
900 class E FOLLY_REQUIRES_TRAILING(
901 !std::is_same<Expected<V, E>, Expected>::value &&
902 std::is_constructible<Value, V&&>::value &&
903 std::is_constructible<Error, E&&>::value)>
904 Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} {
905 *this = std::move(that);
908 FOLLY_REQUIRES(std::is_copy_constructible<Value>::value)
909 constexpr /* implicit */ Expected(const Value& val) noexcept(
910 noexcept(Value(val)))
911 : Base{expected_detail::ValueTag{}, val} {}
913 FOLLY_REQUIRES(std::is_move_constructible<Value>::value)
914 constexpr /* implicit */ Expected(Value&& val) noexcept(
915 noexcept(Value(std::move(val))))
916 : Base{expected_detail::ValueTag{}, std::move(val)} {}
918 template <class T FOLLY_REQUIRES_TRAILING(
919 std::is_convertible<T, Value>::value &&
920 !std::is_convertible<T, Error>::value)>
921 constexpr /* implicit */ Expected(T&& val) noexcept(
922 noexcept(Value(static_cast<T&&>(val))))
923 : Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {}
925 template <class... Ts FOLLY_REQUIRES_TRAILING(
926 std::is_constructible<Value, Ts&&...>::value)>
927 explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
928 noexcept(Value(std::declval<Ts>()...)))
929 : Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {}
933 class... Ts FOLLY_REQUIRES_TRAILING(
934 std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
936 explicit constexpr Expected(
938 std::initializer_list<U> il,
939 Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
940 : Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {}
942 // If overload resolution selects one of these deleted functions, that
943 // means you need to use makeUnexpected
944 /* implicit */ Expected(const Error&) = delete;
945 /* implicit */ Expected(Error&&) = delete;
947 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
948 constexpr Expected(unexpected_t, const Error& err) noexcept(
949 noexcept(Error(err)))
950 : Base{expected_detail::ErrorTag{}, err} {}
952 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
953 constexpr Expected(unexpected_t, Error&& err) noexcept(
954 noexcept(Error(std::move(err))))
955 : Base{expected_detail::ErrorTag{}, std::move(err)} {}
957 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
958 constexpr /* implicit */ Expected(const Unexpected<Error>& err) noexcept(
959 noexcept(Error(err.error())))
960 : Base{expected_detail::ErrorTag{}, err.error()} {}
962 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
963 constexpr /* implicit */ Expected(Unexpected<Error>&& err) noexcept(
964 noexcept(Error(std::move(err.error()))))
965 : Base{expected_detail::ErrorTag{}, std::move(err.error())} {}
968 * Assignment operators
970 Expected& operator=(const Expected& that) = default;
971 Expected& operator=(Expected&& that) = default;
975 class E FOLLY_REQUIRES_TRAILING(
976 !std::is_same<Expected<V, E>, Expected>::value &&
977 expected_detail::IsConvertible<V&&, Value>::value &&
978 expected_detail::IsConvertible<E&&, Error>::value)>
979 Expected& operator=(Expected<V, E> that) {
980 this->assign(std::move(that));
984 FOLLY_REQUIRES(expected_detail::IsCopyable<Value>::value)
985 Expected& operator=(const Value& val) noexcept(
986 expected_detail::IsNothrowCopyable<Value>::value) {
987 this->assignValue(val);
991 FOLLY_REQUIRES(expected_detail::IsMovable<Value>::value)
992 Expected& operator=(Value&& val) noexcept(
993 expected_detail::IsNothrowMovable<Value>::value) {
994 this->assignValue(std::move(val));
998 template <class T FOLLY_REQUIRES_TRAILING(
999 std::is_convertible<T, Value>::value &&
1000 !std::is_convertible<T, Error>::value)>
1001 Expected& operator=(T&& val) {
1002 this->assignValue(static_cast<T&&>(val));
1006 FOLLY_REQUIRES(expected_detail::IsCopyable<Error>::value)
1007 Expected& operator=(const Unexpected<Error>& err) noexcept(
1008 expected_detail::IsNothrowCopyable<Error>::value) {
1009 this->assignError(err.error());
1013 FOLLY_REQUIRES(expected_detail::IsMovable<Error>::value)
1014 Expected& operator=(Unexpected<Error>&& err) noexcept(
1015 expected_detail::IsNothrowMovable<Error>::value) {
1016 this->assignError(std::move(err.error()));
1020 template <class... Ts FOLLY_REQUIRES_TRAILING(
1021 std::is_constructible<Value, Ts&&...>::value)>
1022 void emplace(Ts&&... ts) {
1023 this->assignValue(static_cast<Ts&&>(ts)...);
1029 void swap(Expected& that) noexcept(
1030 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1031 if (this->uninitializedByException() || that.uninitializedByException())
1032 throw BadExpectedAccess();
1036 swap(this->value_, that.value_);
1038 Error e(std::move(that.error_));
1039 that.assignValue(std::move(this->value_));
1040 this->assignError(std::move(e));
1044 swap(this->error_, that.error_);
1046 Error e(std::move(this->error_));
1047 this->assignValue(std::move(that.value_));
1048 that.assignError(std::move(e));
1053 // If overload resolution selects one of these deleted functions, that
1054 // means you need to use makeUnexpected
1055 /* implicit */ Expected& operator=(const Error&) = delete;
1056 /* implicit */ Expected& operator=(Error&&) = delete;
1059 * Relational Operators
1061 template <class Val, class Err>
1062 friend typename std::enable_if<IsEqualityComparable<Val>::value, bool>::type
1063 operator==(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1064 template <class Val, class Err>
1065 friend typename std::enable_if<IsLessThanComparable<Val>::value, bool>::type
1066 operator<(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1071 constexpr bool hasValue() const noexcept {
1072 return expected_detail::Which::eValue == this->which_;
1075 constexpr bool hasError() const noexcept {
1076 return expected_detail::Which::eError == this->which_;
1079 using Base::uninitializedByException;
1081 const Value& value() const& {
1083 return this->Base::value();
1088 return this->Base::value();
1091 Value&& value() && {
1093 return std::move(this->Base::value());
1096 const Error& error() const& {
1098 return this->Base::error();
1103 return this->Base::error();
1106 Error&& error() && {
1108 return std::move(this->Base::error());
1111 // Return a copy of the value if set, or a given default if not.
1113 Value value_or(U&& dflt) const& {
1114 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1115 return this->value_;
1117 return static_cast<U&&>(dflt);
1121 Value value_or(U&& dflt) && {
1122 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1123 return std::move(this->value_);
1125 return static_cast<U&&>(dflt);
1128 explicit constexpr operator bool() const noexcept {
1132 const Value& operator*() const& {
1133 return this->value();
1136 Value& operator*() & {
1137 return this->value();
1140 Value&& operator*() && {
1141 return std::move(this->value());
1144 const Value* operator->() const {
1145 return std::addressof(this->value());
1148 Value* operator->() {
1149 return std::addressof(this->value());
1152 const Value* get_pointer() const& noexcept {
1153 return hasValue() ? std::addressof(this->value_) : nullptr;
1156 Value* get_pointer() & noexcept {
1157 return hasValue() ? std::addressof(this->value_) : nullptr;
1160 Value* get_pointer() && = delete;
1165 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1166 auto then(Fns&&... fns) const& -> decltype(
1167 expected_detail::ExpectedHelper::then_(
1168 std::declval<const Base&>(),
1169 std::declval<Fns>()...)) {
1170 if (this->uninitializedByException())
1171 throw BadExpectedAccess();
1172 return expected_detail::ExpectedHelper::then_(
1173 base(), static_cast<Fns&&>(fns)...);
1176 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1177 auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1178 std::declval<Base&>(),
1179 std::declval<Fns>()...)) {
1180 if (this->uninitializedByException())
1181 throw BadExpectedAccess();
1182 return expected_detail::ExpectedHelper::then_(
1183 base(), static_cast<Fns&&>(fns)...);
1186 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1187 auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1188 std::declval<Base&&>(),
1189 std::declval<Fns>()...)) {
1190 if (this->uninitializedByException())
1191 throw BadExpectedAccess();
1192 return expected_detail::ExpectedHelper::then_(
1193 std::move(base()), static_cast<Fns&&>(fns)...);
1199 template <class Yes, class No = MakeBadExpectedAccess>
1200 auto thenOrThrow(Yes&& yes, No&& no = No{}) const& -> decltype(
1201 std::declval<Yes>()(std::declval<const Value&>())) {
1202 using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1203 if (this->uninitializedByException())
1204 throw BadExpectedAccess();
1205 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1206 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1209 template <class Yes, class No = MakeBadExpectedAccess>
1210 auto thenOrThrow(Yes&& yes, No&& no = No{}) & -> decltype(
1211 std::declval<Yes>()(std::declval<Value&>())) {
1212 using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1213 if (this->uninitializedByException())
1214 throw BadExpectedAccess();
1215 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1216 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1219 template <class Yes, class No = MakeBadExpectedAccess>
1220 auto thenOrThrow(Yes&& yes, No&& no = No{}) && -> decltype(
1221 std::declval<Yes>()(std::declval<Value&&>())) {
1222 using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1223 if (this->uninitializedByException())
1224 throw BadExpectedAccess();
1225 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1226 std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1230 void requireValue() const {
1231 if (UNLIKELY(!hasValue())) {
1232 if (LIKELY(hasError()))
1233 throw typename Unexpected<Error>::BadExpectedAccess(this->error_);
1234 throw BadExpectedAccess();
1238 void requireError() const {
1239 if (UNLIKELY(!hasError())) {
1240 throw BadExpectedAccess();
1244 expected_detail::Which which() const noexcept {
1245 return this->which_;
1249 template <class Value, class Error>
1250 inline typename std::enable_if<IsEqualityComparable<Value>::value, bool>::type
1252 const Expected<Value, Error>& lhs,
1253 const Expected<Value, Error>& rhs) {
1254 if (UNLIKELY(lhs.which_ != rhs.which_))
1255 return UNLIKELY(lhs.uninitializedByException()) ? false
1256 : throw BadExpectedAccess();
1257 if (UNLIKELY(lhs.uninitializedByException()))
1258 throw BadExpectedAccess();
1259 if (UNLIKELY(lhs.hasError()))
1260 return true; // All error states are considered equal
1261 return lhs.value_ == rhs.value_;
1266 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Value>::value)>
1267 inline bool operator!=(
1268 const Expected<Value, Error>& lhs,
1269 const Expected<Value, Error>& rhs) {
1270 return !(rhs == lhs);
1273 template <class Value, class Error>
1274 inline typename std::enable_if<IsLessThanComparable<Value>::value, bool>::type
1276 const Expected<Value, Error>& lhs,
1277 const Expected<Value, Error>& rhs) {
1279 lhs.uninitializedByException() || rhs.uninitializedByException()))
1280 throw BadExpectedAccess();
1281 if (UNLIKELY(lhs.hasError()))
1282 return !rhs.hasError();
1283 if (UNLIKELY(rhs.hasError()))
1285 return lhs.value_ < rhs.value_;
1290 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1291 inline bool operator<=(
1292 const Expected<Value, Error>& lhs,
1293 const Expected<Value, Error>& rhs) {
1294 return !(rhs < lhs);
1299 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1300 inline bool operator>(
1301 const Expected<Value, Error>& lhs,
1302 const Expected<Value, Error>& rhs) {
1308 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1309 inline bool operator>=(
1310 const Expected<Value, Error>& lhs,
1311 const Expected<Value, Error>& rhs) {
1312 return !(lhs < rhs);
1316 * swap Expected values
1318 template <class Error, class Value>
1319 void swap(Expected<Error, Value>& lhs, Expected<Value, Error>& rhs) noexcept(
1320 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1324 template <class Value, class Error>
1325 const Value* get_pointer(const Expected<Value, Error>& ex) noexcept {
1326 return ex.get_pointer();
1329 template <class Value, class Error>
1330 Value* get_pointer(Expected<Value, Error>& ex) noexcept {
1331 return ex.get_pointer();
1335 * For constructing an Expected object from a value, with the specified
1336 * Error type. Usage is as follows:
1338 * enum MyErrorCode { BAD_ERROR, WORSE_ERROR };
1339 * Expected<int, MyErrorCode> myAPI() {
1341 * return i ? makeExpected<MyErrorCode>(i) : makeUnexpected(BAD_ERROR);
1344 template <class Error, class Value>
1345 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
1347 return Expected<typename std::decay<Value>::type, Error>{
1348 in_place, static_cast<Value&&>(val)};
1351 // Suppress comparability of Optional<T> with T, despite implicit conversion.
1352 template <class Value, class Error>
1353 bool operator==(const Expected<Value, Error>&, const Value& other) = delete;
1354 template <class Value, class Error>
1355 bool operator!=(const Expected<Value, Error>&, const Value& other) = delete;
1356 template <class Value, class Error>
1357 bool operator<(const Expected<Value, Error>&, const Value& other) = delete;
1358 template <class Value, class Error>
1359 bool operator<=(const Expected<Value, Error>&, const Value& other) = delete;
1360 template <class Value, class Error>
1361 bool operator>=(const Expected<Value, Error>&, const Value& other) = delete;
1362 template <class Value, class Error>
1363 bool operator>(const Expected<Value, Error>&, const Value& other) = delete;
1364 template <class Value, class Error>
1365 bool operator==(const Value& other, const Expected<Value, Error>&) = delete;
1366 template <class Value, class Error>
1367 bool operator!=(const Value& other, const Expected<Value, Error>&) = delete;
1368 template <class Value, class Error>
1369 bool operator<(const Value& other, const Expected<Value, Error>&) = delete;
1370 template <class Value, class Error>
1371 bool operator<=(const Value& other, const Expected<Value, Error>&) = delete;
1372 template <class Value, class Error>
1373 bool operator>=(const Value& other, const Expected<Value, Error>&) = delete;
1374 template <class Value, class Error>
1375 bool operator>(const Value& other, const Expected<Value, Error>&) = delete;
1377 } // namespace folly
1379 #if defined(__GNUC__) && !defined(__clang__)
1380 #pragma GCC diagnostic pop
1383 #undef FOLLY_REQUIRES
1384 #undef FOLLY_REQUIRES_TRAILING