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 {
95 template <template <class...> class Trait, class... Ts>
96 using StrictAllOf = StrictConjunction<Trait<Ts>...>;
99 using IsCopyable = StrictConjunction<
100 std::is_copy_constructible<T>,
101 std::is_copy_assignable<T>>;
104 using IsMovable = StrictConjunction<
105 std::is_move_constructible<T>,
106 std::is_move_assignable<T>>;
109 using IsNothrowCopyable = StrictConjunction<
110 std::is_nothrow_copy_constructible<T>,
111 std::is_nothrow_copy_assignable<T>>;
114 using IsNothrowMovable = StrictConjunction<
115 std::is_nothrow_move_constructible<T>,
116 std::is_nothrow_move_assignable<T>>;
118 template <class From, class To>
119 using IsConvertible = StrictConjunction<
120 std::is_constructible<To, From>,
121 std::is_assignable<To&, From>>;
123 template <class T, class U>
124 auto doEmplaceAssign(int, T& t, U&& u) -> decltype(void(t = (U &&)u)) {
128 template <class T, class U>
129 auto doEmplaceAssign(long, T& t, U&& u) -> decltype(void(T((U &&)u))) {
131 ::new ((void*)std::addressof(t)) T((U &&)u);
134 template <class T, class... Us>
135 auto doEmplaceAssign(int, T& t, Us&&... us)
136 -> decltype(void(t = T((Us &&)us...))) {
140 template <class T, class... Us>
141 auto doEmplaceAssign(long, T& t, Us&&... us)
142 -> decltype(void(T((Us &&)us...))) {
144 ::new ((void*)std::addressof(t)) T((Us &&)us...);
150 enum class Which : unsigned char { eEmpty, eValue, eError };
151 enum class StorageType { ePODStruct, ePODUnion, eUnion };
153 template <class Value, class Error>
154 constexpr StorageType getStorageType() {
155 return StrictAllOf<IsTriviallyCopyable, Value, Error>::value
156 ? (sizeof(std::pair<Value, Error>) <= sizeof(void * [2]) &&
157 StrictAllOf<std::is_trivial, Value, Error>::value
158 ? StorageType::ePODStruct
159 : StorageType::ePODUnion)
160 : StorageType::eUnion;
166 StorageType = expected_detail::getStorageType<Value, Error>()> // ePODUnion
167 struct ExpectedStorage {
168 using value_type = Value;
169 using error_type = Error;
177 template <class E = Error, class = decltype(E())>
178 constexpr ExpectedStorage() noexcept(noexcept(E()))
179 : error_(), which_(Which::eError) {}
180 explicit constexpr ExpectedStorage(EmptyTag) noexcept
181 : ch_(), which_(Which::eEmpty) {}
182 template <class... Vs>
183 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
184 noexcept(Value(static_cast<Vs&&>(vs)...)))
185 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
186 template <class... Es>
187 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
188 noexcept(Error(static_cast<Es&&>(es)...)))
189 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
190 void clear() noexcept {}
191 static constexpr bool uninitializedByException() noexcept {
192 // Although which_ may temporarily be eEmpty during construction, it
193 // is always either eValue or eError for a fully-constructed Expected.
196 template <class... Vs>
197 void assignValue(Vs&&... vs) {
198 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
199 which_ = Which::eValue;
201 template <class... Es>
202 void assignError(Es&&... es) {
203 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
204 which_ = Which::eError;
206 template <class Other>
207 void assign(Other&& that) {
208 switch (that.which_) {
210 this->assignValue(static_cast<Other&&>(that).value());
213 this->assignError(static_cast<Other&&>(that).error());
223 const Value& value() const& {
227 return std::move(value_);
232 const Error& error() const& {
236 return std::move(error_);
240 template <class Value, class Error>
241 struct ExpectedUnion {
249 explicit constexpr ExpectedUnion(EmptyTag = {}) noexcept
250 : ch_(), which_(Which::eEmpty) {}
251 template <class... Vs>
252 explicit constexpr ExpectedUnion(ValueTag, Vs&&... vs) noexcept(
253 noexcept(Value(static_cast<Vs&&>(vs)...)))
254 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
255 template <class... Es>
256 explicit constexpr ExpectedUnion(ErrorTag, Es&&... es) noexcept(
257 noexcept(Error(static_cast<Es&&>(es)...)))
258 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
259 ExpectedUnion(const ExpectedUnion&) {}
260 ExpectedUnion(ExpectedUnion&&) noexcept {}
261 ExpectedUnion& operator=(const ExpectedUnion&) {
264 ExpectedUnion& operator=(ExpectedUnion&&) noexcept {
271 const Value& value() const& {
275 return std::move(value_);
280 const Error& error() const& {
284 return std::move(error_);
288 template <class Derived, bool, bool Noexcept>
289 struct CopyConstructible {
290 CopyConstructible() = default;
291 CopyConstructible(const CopyConstructible& that) noexcept(Noexcept) {
292 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
294 CopyConstructible(CopyConstructible&&) = default;
295 CopyConstructible& operator=(const CopyConstructible&) = default;
296 CopyConstructible& operator=(CopyConstructible&&) = default;
299 template <class Derived, bool Noexcept>
300 struct CopyConstructible<Derived, false, Noexcept> {
301 CopyConstructible() = default;
302 CopyConstructible(const CopyConstructible&) = delete;
303 CopyConstructible(CopyConstructible&&) = default;
304 CopyConstructible& operator=(const CopyConstructible&) = default;
305 CopyConstructible& operator=(CopyConstructible&&) = default;
308 template <class Derived, bool, bool Noexcept>
309 struct MoveConstructible {
310 MoveConstructible() = default;
311 MoveConstructible(const MoveConstructible&) = default;
312 MoveConstructible(MoveConstructible&& that) noexcept(Noexcept) {
313 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
315 MoveConstructible& operator=(const MoveConstructible&) = default;
316 MoveConstructible& operator=(MoveConstructible&&) = default;
319 template <class Derived, bool Noexcept>
320 struct MoveConstructible<Derived, false, Noexcept> {
321 MoveConstructible() = default;
322 MoveConstructible(const MoveConstructible&) = default;
323 MoveConstructible(MoveConstructible&&) = delete;
324 MoveConstructible& operator=(const MoveConstructible&) = default;
325 MoveConstructible& operator=(MoveConstructible&&) = default;
328 template <class Derived, bool, bool Noexcept>
329 struct CopyAssignable {
330 CopyAssignable() = default;
331 CopyAssignable(const CopyAssignable&) = default;
332 CopyAssignable(CopyAssignable&&) = default;
333 CopyAssignable& operator=(const CopyAssignable& that) noexcept(Noexcept) {
334 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
337 CopyAssignable& operator=(CopyAssignable&&) = default;
340 template <class Derived, bool Noexcept>
341 struct CopyAssignable<Derived, false, Noexcept> {
342 CopyAssignable() = default;
343 CopyAssignable(const CopyAssignable&) = default;
344 CopyAssignable(CopyAssignable&&) = default;
345 CopyAssignable& operator=(const CopyAssignable&) = delete;
346 CopyAssignable& operator=(CopyAssignable&&) = default;
349 template <class Derived, bool, bool Noexcept>
350 struct MoveAssignable {
351 MoveAssignable() = default;
352 MoveAssignable(const MoveAssignable&) = default;
353 MoveAssignable(MoveAssignable&&) = default;
354 MoveAssignable& operator=(const MoveAssignable&) = default;
355 MoveAssignable& operator=(MoveAssignable&& that) noexcept(Noexcept) {
356 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
361 template <class Derived, bool Noexcept>
362 struct MoveAssignable<Derived, false, Noexcept> {
363 MoveAssignable() = default;
364 MoveAssignable(const MoveAssignable&) = default;
365 MoveAssignable(MoveAssignable&&) = default;
366 MoveAssignable& operator=(const MoveAssignable&) = default;
367 MoveAssignable& operator=(MoveAssignable&& that) = delete;
370 template <class Value, class Error>
371 struct ExpectedStorage<Value, Error, StorageType::eUnion>
372 : ExpectedUnion<Value, Error>,
374 ExpectedStorage<Value, Error, StorageType::eUnion>,
375 StrictAllOf<std::is_copy_constructible, Value, Error>::value,
376 StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::value>,
378 ExpectedStorage<Value, Error, StorageType::eUnion>,
379 StrictAllOf<std::is_move_constructible, Value, Error>::value,
380 StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::value>,
382 ExpectedStorage<Value, Error, StorageType::eUnion>,
383 StrictAllOf<IsCopyable, Value, Error>::value,
384 StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
386 ExpectedStorage<Value, Error, StorageType::eUnion>,
387 StrictAllOf<IsMovable, Value, Error>::value,
388 StrictAllOf<IsNothrowMovable, Value, Error>::value> {
389 using value_type = Value;
390 using error_type = Error;
391 using Base = ExpectedUnion<Value, Error>;
392 template <class E = Error, class = decltype(E())>
393 constexpr ExpectedStorage() noexcept(noexcept(E())) : Base{ErrorTag{}} {}
394 ExpectedStorage(const ExpectedStorage&) = default;
395 ExpectedStorage(ExpectedStorage&&) = default;
396 ExpectedStorage& operator=(const ExpectedStorage&) = default;
397 ExpectedStorage& operator=(ExpectedStorage&&) = default;
398 using ExpectedUnion<Value, Error>::ExpectedUnion;
402 void clear() noexcept {
403 switch (this->which_) {
405 this->value().~Value();
408 this->error().~Error();
413 this->which_ = Which::eEmpty;
415 bool uninitializedByException() const noexcept {
416 return this->which_ == Which::eEmpty;
418 template <class... Vs>
419 void assignValue(Vs&&... vs) {
420 if (this->which_ == Which::eValue) {
421 expected_detail::doEmplaceAssign(
422 0, this->value(), static_cast<Vs&&>(vs)...);
425 ::new ((void*)std::addressof(this->value()))
426 Value(static_cast<Vs&&>(vs)...);
427 this->which_ = Which::eValue;
430 template <class... Es>
431 void assignError(Es&&... es) {
432 if (this->which_ == Which::eError) {
433 expected_detail::doEmplaceAssign(
434 0, this->error(), static_cast<Es&&>(es)...);
437 ::new ((void*)std::addressof(this->error()))
438 Error(static_cast<Es&&>(es)...);
439 this->which_ = Which::eError;
442 bool isThis(const ExpectedStorage* that) const {
445 constexpr bool isSelfAssign(const void*) const {
448 template <class Other>
449 void assign(Other&& that) {
450 if (isSelfAssign(&that))
452 switch (that.which_) {
454 this->assignValue(static_cast<Other&&>(that).value());
457 this->assignError(static_cast<Other&&>(that).error());
466 // For small (pointer-sized) trivial types, a struct is faster than a union.
467 template <class Value, class Error>
468 struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
469 using value_type = Value;
470 using error_type = Error;
475 constexpr ExpectedStorage() noexcept
476 : which_(Which::eError), error_(), value_() {}
477 explicit constexpr ExpectedStorage(EmptyTag) noexcept
478 : which_(Which::eEmpty), error_(), value_() {}
479 template <class... Vs>
480 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
481 noexcept(Value(static_cast<Vs&&>(vs)...)))
482 : which_(Which::eValue), error_(), value_(static_cast<Vs&&>(vs)...) {}
483 template <class... Es>
484 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
485 noexcept(Error(static_cast<Es&&>(es)...)))
486 : which_(Which::eError), error_(static_cast<Es&&>(es)...), value_() {}
487 void clear() noexcept {}
488 constexpr static bool uninitializedByException() noexcept {
491 template <class... Vs>
492 void assignValue(Vs&&... vs) {
493 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
494 which_ = Which::eValue;
496 template <class... Es>
497 void assignError(Es&&... es) {
498 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
499 which_ = Which::eError;
501 template <class Other>
502 void assign(Other&& that) {
503 switch (that.which_) {
505 this->assignValue(static_cast<Other&&>(that).value());
508 this->assignError(static_cast<Other&&>(that).error());
518 const Value& value() const& {
522 return std::move(value_);
527 const Error& error() const& {
531 return std::move(error_);
535 namespace expected_detail_ExpectedHelper {
536 // Tricky hack so that Expected::then can handle lambdas that return void
538 inline T&& operator,(T&& t, Unit) noexcept {
539 return static_cast<T&&>(t);
542 struct ExpectedHelper {
543 template <class Error, class T>
544 static constexpr Expected<T, Error> return_(T t) {
545 return folly::makeExpected<Error>(t);
550 class U FOLLY_REQUIRES_TRAILING(
551 expected_detail::IsConvertible<U&&, Error>::value)>
552 static constexpr Expected<T, Error> return_(Expected<T, U> t) {
556 template <class This>
557 static typename std::decay<This>::type then_(This&& ex) {
558 return static_cast<This&&>(ex);
565 class E = ExpectedErrorType<This>,
566 class T = ExpectedHelper>
567 static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
568 T::template return_<E>(
569 (std::declval<Fn>()(std::declval<This>().value()), unit)),
570 std::declval<Fns>()...)) {
571 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
573 T::template return_<E>(
574 // Uses the comma operator defined above IFF the lambda
576 (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
577 static_cast<Fns&&>(fns)...);
578 return makeUnexpected(static_cast<This&&>(ex).error());
585 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
586 class Err = decltype(std::declval<No>()(std::declval<This>().error()))
587 FOLLY_REQUIRES_TRAILING(!std::is_void<Err>::value)>
588 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
589 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
590 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
591 throw static_cast<No&&>(no)(static_cast<This&&>(ex).error());
598 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
599 class Err = decltype(std::declval<No>()(std::declval<This&>().error()))
600 FOLLY_REQUIRES_TRAILING(std::is_void<Err>::value)>
601 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
602 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
603 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
604 static_cast<No&&>(no)(ex.error());
605 throw typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess()(
606 static_cast<This&&>(ex).error());
610 /* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
612 struct UnexpectedTag {};
614 } // namespace expected_detail
617 expected_detail::UnexpectedTag (&)(expected_detail::UnexpectedTag);
619 inline expected_detail::UnexpectedTag unexpected(
620 expected_detail::UnexpectedTag = {}) {
625 * An exception type thrown by Expected on catastrophic logic errors.
627 class BadExpectedAccess : public std::logic_error {
629 BadExpectedAccess() : std::logic_error("bad Expected access") {}
633 * Unexpected - a helper type used to disambiguate the construction of
634 * Expected objects in the error state.
636 template <class Error>
637 class Unexpected final {
639 friend class Unexpected;
640 template <class V, class E>
641 friend class Expected;
642 friend struct expected_detail::ExpectedHelper;
646 * Unexpected::BadExpectedAccess - An exception type thrown by Expected
647 * when the user tries to access the nested value but the Expected object is
648 * actually storing an error code.
650 class BadExpectedAccess : public folly::BadExpectedAccess {
652 explicit BadExpectedAccess(Error err)
653 : folly::BadExpectedAccess(), error_(std::move(err)) {}
655 * The error code that was held by the Expected object when the user
656 * erroneously requested the value.
658 Error error() const {
669 Unexpected() = default;
670 Unexpected(const Unexpected&) = default;
671 Unexpected(Unexpected&&) = default;
672 Unexpected& operator=(const Unexpected&) = default;
673 Unexpected& operator=(Unexpected&&) = default;
674 constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {}
675 constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {}
677 template <class Other FOLLY_REQUIRES_TRAILING(
678 std::is_constructible<Error, Other&&>::value)>
679 constexpr /* implicit */ Unexpected(Unexpected<Other> that)
680 : error_(std::move(that.error())) {}
685 template <class Other FOLLY_REQUIRES_TRAILING(
686 std::is_assignable<Error&, Other&&>::value)>
687 Unexpected& operator=(Unexpected<Other> that) {
688 error_ = std::move(that.error());
697 const Error& error() const& {
701 return std::move(error_);
705 * Relational operators
707 FOLLY_REQUIRES(IsEqualityComparable<Error>::value)
708 friend bool operator==(const Unexpected& lhs, const Unexpected& rhs) {
709 return lhs.error() == rhs.error();
711 FOLLY_REQUIRES(IsEqualityComparable<Error>::value)
712 friend bool operator!=(const Unexpected& lhs, const Unexpected& rhs) {
713 return !(lhs == rhs);
717 struct MakeBadExpectedAccess {
719 BadExpectedAccess operator()(E&& err) const {
720 return BadExpectedAccess(static_cast<E&&>(err));
728 * For constructing an Unexpected object from an error code. Unexpected objects
729 * are implicitly convertible to Expected object in the error state. Usage is
732 * enum class MyErrorCode { BAD_ERROR, WORSE_ERROR };
733 * Expected<int, MyErrorCode> myAPI() {
735 * return i ? makeExpected<MyErrorCode>(i)
736 * : makeUnexpected(MyErrorCode::BAD_ERROR);
739 template <class Error>
740 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(
742 return Unexpected<typename std::decay<Error>::type>{
743 static_cast<Error&&>(err)};
747 * Expected - For holding a value or an error. Useful as an alternative to
748 * exceptions, for APIs where throwing on failure would be too expensive.
750 * Expected<Value, Error> is a variant over the types Value and Error.
752 * Expected does not offer support for references. Use
753 * Expected<std::reference_wrapper<T>, Error> if your API needs to return a
754 * reference or an error.
756 * Expected offers a continuation-based interface to reduce the boilerplate
757 * of checking error codes. The Expected::then member function takes a lambda
758 * that is to execute should the Expected object contain a value. The return
759 * value of the lambda is wrapped in an Expected and returned. If the lambda is
760 * not executed because the Expected contains an error, the error is returned
761 * immediately in a new Expected object.
763 * Expected<int, Error> funcTheFirst();
764 * Expected<std::string, Error> funcTheSecond() {
765 * return funcTheFirst().then([](int i) { return std::to_string(i); });
768 * The above line of code could more verbosely written as:
770 * Expected<std::string, Error> funcTheSecond() {
771 * if (auto ex = funcTheFirst()) {
772 * return std::to_string(*ex);
774 * return makeUnexpected(ex.error());
777 * Continuations can chain, like:
779 * Expected<D, Error> maybeD = someFunc()
780 * .then([](A a){return B(a);})
781 * .then([](B b){return C(b);})
782 * .then([](C c){return D(c);});
784 * To avoid the redundant error checking that would happen if a call at the
785 * front of the chain returns an error, these call chains can be collaped into
786 * a single call to .then:
788 * Expected<D, Error> maybeD = someFunc()
789 * .then([](A a){return B(a);},
790 * [](B b){return C(b);},
791 * [](C c){return D(c);});
793 * The result of .then() is wrapped into Expected< ~, Error > if it isn't
794 * of that form already. Consider the following code:
796 * extern Expected<std::string, Error> readLineFromIO();
797 * extern Expected<int, Error> parseInt(std::string);
798 * extern int increment(int);
800 * Expected<int, Error> x = readLineFromIO().then(parseInt).then(increment);
802 * From the code above, we see that .then() works both with functions that
803 * return an Expected< ~, Error > (like parseInt) and with ones that return
804 * a plain value (like increment). In the case of parseInt, .then() returns
805 * the result of parseInt as-is. In the case of increment, it wraps the int
806 * that increment returns into an Expected< int, Error >.
808 * Sometimes when using a continuation you would prefer an exception to be
809 * thrown for a value-less Expected. For that you can use .thenOrThrow, as
813 * .thenOrThrow([](A a){return B(a);});
815 * The above call to thenOrThrow will invoke the lambda if the Expected returned
816 * by someFunc() contains a value. Otherwise, it will throw an exception of type
817 * Unexpected<Error>::BadExpectedAccess. If you prefer it throw an exception of
818 * a different type, you can pass a second lambda to thenOrThrow:
821 * .thenOrThrow([](A a){return B(a);},
822 * [](Error e) {throw MyException(e);});
824 * Like C++17's std::variant, Expected offers the almost-never-empty guarantee;
825 * that is, an Expected<Value, Error> almost always contains either a Value or
826 * and Error. Partially-formed Expected objects occur when an assignment to
827 * an Expected object that would change the type of the contained object (Value-
828 * to-Error or vice versa) throws. Trying to access either the contained value
829 * or error object causes Expected to throw folly::BadExpectedAccess.
831 * Expected models OptionalPointee, so calling 'get_pointer(ex)' will return a
832 * pointer to nullptr if the 'ex' is in the error state, and a pointer to the
835 * Expected<int, Error> maybeInt = ...;
836 * if (int* v = get_pointer(maybeInt)) {
837 * cout << *v << endl;
840 template <class Value, class Error>
841 class Expected final : expected_detail::ExpectedStorage<Value, Error> {
842 template <class, class>
843 friend class Expected;
844 template <class, class, expected_detail::StorageType>
845 friend struct expected_detail::ExpectedStorage;
846 friend struct expected_detail::ExpectedHelper;
847 using Base = expected_detail::ExpectedStorage<Value, Error>;
848 using MakeBadExpectedAccess =
849 typename Unexpected<Error>::MakeBadExpectedAccess;
853 const Base& base() const& {
857 return std::move(*this);
861 using value_type = Value;
862 using error_type = Error;
863 using IsTriviallyCopyable = typename expected_detail::
864 StrictAllOf<IsTriviallyCopyable, Value, Error>::type;
867 using rebind = Expected<U, Error>;
870 !std::is_reference<Value>::value,
871 "Expected may not be used with reference types");
873 !std::is_abstract<Value>::value,
874 "Expected may not be used with abstract types");
879 template <class B = Base, class = decltype(B{})>
880 Expected() noexcept(noexcept(B{})) : Base() {}
881 Expected(const Expected& that) = default;
882 Expected(Expected&& that) = default;
886 class E FOLLY_REQUIRES_TRAILING(
887 !std::is_same<Expected<V, E>, Expected>::value &&
888 std::is_constructible<Value, V&&>::value &&
889 std::is_constructible<Error, E&&>::value)>
890 Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} {
891 *this = std::move(that);
894 FOLLY_REQUIRES(std::is_copy_constructible<Value>::value)
895 constexpr /* implicit */ Expected(const Value& val) noexcept(
896 noexcept(Value(val)))
897 : Base{expected_detail::ValueTag{}, val} {}
899 FOLLY_REQUIRES(std::is_move_constructible<Value>::value)
900 constexpr /* implicit */ Expected(Value&& val) noexcept(
901 noexcept(Value(std::move(val))))
902 : Base{expected_detail::ValueTag{}, std::move(val)} {}
904 template <class T FOLLY_REQUIRES_TRAILING(
905 std::is_convertible<T, Value>::value &&
906 !std::is_convertible<T, Error>::value)>
907 constexpr /* implicit */ Expected(T&& val) noexcept(
908 noexcept(Value(static_cast<T&&>(val))))
909 : Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {}
911 template <class... Ts FOLLY_REQUIRES_TRAILING(
912 std::is_constructible<Value, Ts&&...>::value)>
913 explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
914 noexcept(Value(std::declval<Ts>()...)))
915 : Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {}
919 class... Ts FOLLY_REQUIRES_TRAILING(
920 std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
922 explicit constexpr Expected(
924 std::initializer_list<U> il,
925 Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
926 : Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {}
928 // If overload resolution selects one of these deleted functions, that
929 // means you need to use makeUnexpected
930 /* implicit */ Expected(const Error&) = delete;
931 /* implicit */ Expected(Error&&) = delete;
933 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
934 constexpr Expected(unexpected_t, const Error& err) noexcept(
935 noexcept(Error(err)))
936 : Base{expected_detail::ErrorTag{}, err} {}
938 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
939 constexpr Expected(unexpected_t, Error&& err) noexcept(
940 noexcept(Error(std::move(err))))
941 : Base{expected_detail::ErrorTag{}, std::move(err)} {}
943 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
944 constexpr /* implicit */ Expected(const Unexpected<Error>& err) noexcept(
945 noexcept(Error(err.error())))
946 : Base{expected_detail::ErrorTag{}, err.error()} {}
948 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
949 constexpr /* implicit */ Expected(Unexpected<Error>&& err) noexcept(
950 noexcept(Error(std::move(err.error()))))
951 : Base{expected_detail::ErrorTag{}, std::move(err.error())} {}
954 * Assignment operators
956 Expected& operator=(const Expected& that) = default;
957 Expected& operator=(Expected&& that) = default;
961 class E FOLLY_REQUIRES_TRAILING(
962 !std::is_same<Expected<V, E>, Expected>::value &&
963 expected_detail::IsConvertible<V&&, Value>::value &&
964 expected_detail::IsConvertible<E&&, Error>::value)>
965 Expected& operator=(Expected<V, E> that) {
966 this->assign(std::move(that));
970 FOLLY_REQUIRES(expected_detail::IsCopyable<Value>::value)
971 Expected& operator=(const Value& val) noexcept(
972 expected_detail::IsNothrowCopyable<Value>::value) {
973 this->assignValue(val);
977 FOLLY_REQUIRES(expected_detail::IsMovable<Value>::value)
978 Expected& operator=(Value&& val) noexcept(
979 expected_detail::IsNothrowMovable<Value>::value) {
980 this->assignValue(std::move(val));
984 template <class T FOLLY_REQUIRES_TRAILING(
985 std::is_convertible<T, Value>::value &&
986 !std::is_convertible<T, Error>::value)>
987 Expected& operator=(T&& val) {
988 this->assignValue(static_cast<T&&>(val));
992 FOLLY_REQUIRES(expected_detail::IsCopyable<Error>::value)
993 Expected& operator=(const Unexpected<Error>& err) noexcept(
994 expected_detail::IsNothrowCopyable<Error>::value) {
995 this->assignError(err.error());
999 FOLLY_REQUIRES(expected_detail::IsMovable<Error>::value)
1000 Expected& operator=(Unexpected<Error>&& err) noexcept(
1001 expected_detail::IsNothrowMovable<Error>::value) {
1002 this->assignError(std::move(err.error()));
1006 template <class... Ts FOLLY_REQUIRES_TRAILING(
1007 std::is_constructible<Value, Ts&&...>::value)>
1008 void emplace(Ts&&... ts) {
1009 this->assignValue(static_cast<Ts&&>(ts)...);
1015 void swap(Expected& that) noexcept(
1016 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1017 if (this->uninitializedByException() || that.uninitializedByException())
1018 throw BadExpectedAccess();
1022 swap(this->value_, that.value_);
1024 Error e(std::move(that.error_));
1025 that.assignValue(std::move(this->value_));
1026 this->assignError(std::move(e));
1030 swap(this->error_, that.error_);
1032 Error e(std::move(this->error_));
1033 this->assignValue(std::move(that.value_));
1034 that.assignError(std::move(e));
1039 // If overload resolution selects one of these deleted functions, that
1040 // means you need to use makeUnexpected
1041 /* implicit */ Expected& operator=(const Error&) = delete;
1042 /* implicit */ Expected& operator=(Error&&) = delete;
1045 * Relational Operators
1047 FOLLY_REQUIRES(IsEqualityComparable<Value>::value)
1048 friend bool operator==(const Expected& lhs, const Expected& rhs) {
1049 if (UNLIKELY(lhs.which_ != rhs.which_))
1050 return UNLIKELY(lhs.uninitializedByException())
1052 : throw BadExpectedAccess();
1053 if (UNLIKELY(lhs.uninitializedByException()))
1054 throw BadExpectedAccess();
1055 if (UNLIKELY(lhs.hasError()))
1056 return true; // All error states are considered equal
1057 return lhs.value_ == rhs.value_;
1060 FOLLY_REQUIRES(IsEqualityComparable<Value>::value)
1061 friend bool operator!=(const Expected& lhs, const Expected& rhs) {
1062 return !(lhs == rhs);
1065 FOLLY_REQUIRES(IsLessThanComparable<Value>::value)
1066 friend bool operator<(const Expected& lhs, const Expected& rhs) {
1068 lhs.uninitializedByException() || rhs.uninitializedByException()))
1069 throw BadExpectedAccess();
1070 if (UNLIKELY(lhs.hasError()))
1071 return !rhs.hasError();
1072 if (UNLIKELY(rhs.hasError()))
1074 return lhs.value_ < rhs.value_;
1077 FOLLY_REQUIRES(IsLessThanComparable<Value>::value)
1078 friend bool operator<=(const Expected& lhs, const Expected& rhs) {
1079 return !(rhs < lhs);
1082 FOLLY_REQUIRES(IsLessThanComparable<Value>::value)
1083 friend bool operator>(const Expected& lhs, const Expected& rhs) {
1087 FOLLY_REQUIRES(IsLessThanComparable<Value>::value)
1088 friend bool operator>=(const Expected& lhs, const Expected& rhs) {
1089 return !(lhs < rhs);
1095 constexpr bool hasValue() const noexcept {
1096 return expected_detail::Which::eValue == this->which_;
1099 constexpr bool hasError() const noexcept {
1100 return expected_detail::Which::eError == this->which_;
1103 using Base::uninitializedByException;
1105 const Value& value() const& {
1107 return this->Base::value();
1112 return this->Base::value();
1115 Value&& value() && {
1117 return std::move(this->Base::value());
1120 const Error& error() const& {
1122 return this->Base::error();
1127 return this->Base::error();
1130 Error&& error() && {
1132 return std::move(this->Base::error());
1135 // Return a copy of the value if set, or a given default if not.
1137 Value value_or(U&& dflt) const& {
1138 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1139 return this->value_;
1141 return static_cast<U&&>(dflt);
1145 Value value_or(U&& dflt) && {
1146 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1147 return std::move(this->value_);
1149 return static_cast<U&&>(dflt);
1152 explicit constexpr operator bool() const noexcept {
1156 const Value& operator*() const& {
1157 return this->value();
1160 Value& operator*() & {
1161 return this->value();
1164 Value&& operator*() && {
1165 return std::move(this->value());
1168 const Value* operator->() const {
1169 return std::addressof(this->value());
1172 Value* operator->() {
1173 return std::addressof(this->value());
1176 const Value* get_pointer() const& noexcept {
1177 return hasValue() ? std::addressof(this->value_) : nullptr;
1180 Value* get_pointer() & noexcept {
1181 return hasValue() ? std::addressof(this->value_) : nullptr;
1184 Value* get_pointer() && = delete;
1189 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1190 auto then(Fns&&... fns) const& -> decltype(
1191 expected_detail::ExpectedHelper::then_(
1192 std::declval<const Base&>(),
1193 std::declval<Fns>()...)) {
1194 if (this->uninitializedByException())
1195 throw BadExpectedAccess();
1196 return expected_detail::ExpectedHelper::then_(
1197 base(), static_cast<Fns&&>(fns)...);
1200 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1201 auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1202 std::declval<Base&>(),
1203 std::declval<Fns>()...)) {
1204 if (this->uninitializedByException())
1205 throw BadExpectedAccess();
1206 return expected_detail::ExpectedHelper::then_(
1207 base(), static_cast<Fns&&>(fns)...);
1210 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1211 auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1212 std::declval<Base&&>(),
1213 std::declval<Fns>()...)) {
1214 if (this->uninitializedByException())
1215 throw BadExpectedAccess();
1216 return expected_detail::ExpectedHelper::then_(
1217 std::move(base()), static_cast<Fns&&>(fns)...);
1223 template <class Yes, class No = MakeBadExpectedAccess>
1224 auto thenOrThrow(Yes&& yes, No&& no = No()) const& -> decltype(
1225 std::declval<Yes>()(std::declval<const Value&>())) {
1226 using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1227 if (this->uninitializedByException())
1228 throw BadExpectedAccess();
1229 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1230 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1233 template <class Yes, class No = MakeBadExpectedAccess>
1234 auto thenOrThrow(Yes&& yes, No&& no = No()) & -> decltype(
1235 std::declval<Yes>()(std::declval<Value&>())) {
1236 using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1237 if (this->uninitializedByException())
1238 throw BadExpectedAccess();
1239 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1240 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1243 template <class Yes, class No = MakeBadExpectedAccess>
1244 auto thenOrThrow(Yes&& yes, No&& no = No()) && -> decltype(
1245 std::declval<Yes>()(std::declval<Value&&>())) {
1246 using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1247 if (this->uninitializedByException())
1248 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_);
1258 throw BadExpectedAccess();
1262 void requireError() const {
1263 if (UNLIKELY(!hasError())) {
1264 throw BadExpectedAccess();
1268 expected_detail::Which which() const noexcept {
1269 return this->which_;
1274 * swap Expected values
1276 template <class Error, class Value>
1277 void swap(Expected<Error, Value>& lhs, Expected<Value, Error>& rhs) noexcept(
1278 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1282 template <class Value, class Error>
1283 const Value* get_pointer(const Expected<Value, Error>& ex) noexcept {
1284 return ex.get_pointer();
1287 template <class Value, class Error>
1288 Value* get_pointer(Expected<Value, Error>& ex) noexcept {
1289 return ex.get_pointer();
1293 * For constructing an Expected object from a value, with the specified
1294 * Error type. Usage is as follows:
1296 * enum MyErrorCode { BAD_ERROR, WORSE_ERROR };
1297 * Expected<int, MyErrorCode> myAPI() {
1299 * return i ? makeExpected<MyErrorCode>(i) : makeUnexpected(BAD_ERROR);
1302 template <class Error, class Value>
1303 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
1305 return Expected<typename std::decay<Value>::type, Error>{
1306 in_place, static_cast<Value&&>(val)};
1309 // Suppress comparability of Optional<T> with T, despite implicit conversion.
1310 template <class Value, class Error>
1311 bool operator==(const Expected<Value, Error>&, const Value& other) = delete;
1312 template <class Value, class Error>
1313 bool operator!=(const Expected<Value, Error>&, const Value& other) = delete;
1314 template <class Value, class Error>
1315 bool operator<(const Expected<Value, Error>&, const Value& other) = delete;
1316 template <class Value, class Error>
1317 bool operator<=(const Expected<Value, Error>&, const Value& other) = delete;
1318 template <class Value, class Error>
1319 bool operator>=(const Expected<Value, Error>&, const Value& other) = delete;
1320 template <class Value, class Error>
1321 bool operator>(const Expected<Value, Error>&, const Value& other) = delete;
1322 template <class Value, class Error>
1323 bool operator==(const Value& other, const Expected<Value, Error>&) = delete;
1324 template <class Value, class Error>
1325 bool operator!=(const Value& other, const Expected<Value, Error>&) = delete;
1326 template <class Value, class Error>
1327 bool operator<(const Value& other, const Expected<Value, Error>&) = delete;
1328 template <class Value, class Error>
1329 bool operator<=(const Value& other, const Expected<Value, Error>&) = delete;
1330 template <class Value, class Error>
1331 bool operator>=(const Value& other, const Expected<Value, Error>&) = delete;
1332 template <class Value, class Error>
1333 bool operator>(const Value& other, const Expected<Value, Error>&) = delete;
1335 } // namespace folly
1337 #if defined(__GNUC__) && !defined(__clang__)
1338 #pragma GCC diagnostic pop
1341 #undef FOLLY_REQUIRES
1342 #undef FOLLY_REQUIRES_TRAILING