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 {
256 explicit constexpr ExpectedUnion(EmptyTag = {}) noexcept
257 : ch_(), which_(Which::eEmpty) {}
258 template <class... Vs>
259 explicit constexpr ExpectedUnion(ValueTag, Vs&&... vs) noexcept(
260 noexcept(Value(static_cast<Vs&&>(vs)...)))
261 : value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {}
262 template <class... Es>
263 explicit constexpr ExpectedUnion(ErrorTag, Es&&... es) noexcept(
264 noexcept(Error(static_cast<Es&&>(es)...)))
265 : error_(static_cast<Es&&>(es)...), which_(Which::eError) {}
266 ExpectedUnion(const ExpectedUnion&) {}
267 ExpectedUnion(ExpectedUnion&&) noexcept {}
268 ExpectedUnion& operator=(const ExpectedUnion&) {
271 ExpectedUnion& operator=(ExpectedUnion&&) noexcept {
278 const Value& value() const& {
282 return std::move(value_);
287 const Error& error() const& {
291 return std::move(error_);
295 template <class Derived, bool, bool Noexcept>
296 struct CopyConstructible {
297 constexpr CopyConstructible() = default;
298 CopyConstructible(const CopyConstructible& that) noexcept(Noexcept) {
299 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
301 constexpr CopyConstructible(CopyConstructible&&) = default;
302 CopyConstructible& operator=(const CopyConstructible&) = default;
303 CopyConstructible& operator=(CopyConstructible&&) = default;
306 template <class Derived, bool Noexcept>
307 struct CopyConstructible<Derived, false, Noexcept> {
308 constexpr CopyConstructible() = default;
309 CopyConstructible(const CopyConstructible&) = delete;
310 constexpr CopyConstructible(CopyConstructible&&) = default;
311 CopyConstructible& operator=(const CopyConstructible&) = default;
312 CopyConstructible& operator=(CopyConstructible&&) = default;
315 template <class Derived, bool, bool Noexcept>
316 struct MoveConstructible {
317 constexpr MoveConstructible() = default;
318 constexpr MoveConstructible(const MoveConstructible&) = default;
319 MoveConstructible(MoveConstructible&& that) noexcept(Noexcept) {
320 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
322 MoveConstructible& operator=(const MoveConstructible&) = default;
323 MoveConstructible& operator=(MoveConstructible&&) = default;
326 template <class Derived, bool Noexcept>
327 struct MoveConstructible<Derived, false, Noexcept> {
328 constexpr MoveConstructible() = default;
329 constexpr MoveConstructible(const MoveConstructible&) = default;
330 MoveConstructible(MoveConstructible&&) = delete;
331 MoveConstructible& operator=(const MoveConstructible&) = default;
332 MoveConstructible& operator=(MoveConstructible&&) = default;
335 template <class Derived, bool, bool Noexcept>
336 struct CopyAssignable {
337 constexpr CopyAssignable() = default;
338 constexpr CopyAssignable(const CopyAssignable&) = default;
339 constexpr CopyAssignable(CopyAssignable&&) = default;
340 CopyAssignable& operator=(const CopyAssignable& that) noexcept(Noexcept) {
341 static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
344 CopyAssignable& operator=(CopyAssignable&&) = default;
347 template <class Derived, bool Noexcept>
348 struct CopyAssignable<Derived, false, Noexcept> {
349 constexpr CopyAssignable() = default;
350 constexpr CopyAssignable(const CopyAssignable&) = default;
351 constexpr CopyAssignable(CopyAssignable&&) = default;
352 CopyAssignable& operator=(const CopyAssignable&) = delete;
353 CopyAssignable& operator=(CopyAssignable&&) = default;
356 template <class Derived, bool, bool Noexcept>
357 struct MoveAssignable {
358 constexpr MoveAssignable() = default;
359 constexpr MoveAssignable(const MoveAssignable&) = default;
360 constexpr MoveAssignable(MoveAssignable&&) = default;
361 MoveAssignable& operator=(const MoveAssignable&) = default;
362 MoveAssignable& operator=(MoveAssignable&& that) noexcept(Noexcept) {
363 static_cast<Derived*>(this)->assign(std::move(static_cast<Derived&>(that)));
368 template <class Derived, bool Noexcept>
369 struct MoveAssignable<Derived, false, Noexcept> {
370 constexpr MoveAssignable() = default;
371 constexpr MoveAssignable(const MoveAssignable&) = default;
372 constexpr MoveAssignable(MoveAssignable&&) = default;
373 MoveAssignable& operator=(const MoveAssignable&) = default;
374 MoveAssignable& operator=(MoveAssignable&& that) = delete;
377 template <class Value, class Error>
378 struct ExpectedStorage<Value, Error, StorageType::eUnion>
379 : ExpectedUnion<Value, Error>,
381 ExpectedStorage<Value, Error, StorageType::eUnion>,
382 StrictAllOf<std::is_copy_constructible, Value, Error>::value,
383 StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::value>,
385 ExpectedStorage<Value, Error, StorageType::eUnion>,
386 StrictAllOf<std::is_move_constructible, Value, Error>::value,
387 StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::value>,
389 ExpectedStorage<Value, Error, StorageType::eUnion>,
390 StrictAllOf<IsCopyable, Value, Error>::value,
391 StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
393 ExpectedStorage<Value, Error, StorageType::eUnion>,
394 StrictAllOf<IsMovable, Value, Error>::value,
395 StrictAllOf<IsNothrowMovable, Value, Error>::value> {
396 using value_type = Value;
397 using error_type = Error;
398 using Base = ExpectedUnion<Value, Error>;
399 template <class E = Error, class = decltype(E())>
400 constexpr ExpectedStorage() noexcept(noexcept(E())) : Base{ErrorTag{}} {}
401 ExpectedStorage(const ExpectedStorage&) = default;
402 ExpectedStorage(ExpectedStorage&&) = default;
403 ExpectedStorage& operator=(const ExpectedStorage&) = default;
404 ExpectedStorage& operator=(ExpectedStorage&&) = default;
405 using ExpectedUnion<Value, Error>::ExpectedUnion;
409 void clear() noexcept {
410 switch (this->which_) {
412 this->value().~Value();
415 this->error().~Error();
420 this->which_ = Which::eEmpty;
422 bool uninitializedByException() const noexcept {
423 return this->which_ == Which::eEmpty;
425 template <class... Vs>
426 void assignValue(Vs&&... vs) {
427 if (this->which_ == Which::eValue) {
428 expected_detail::doEmplaceAssign(
429 0, this->value(), static_cast<Vs&&>(vs)...);
432 ::new ((void*)std::addressof(this->value()))
433 Value(static_cast<Vs&&>(vs)...);
434 this->which_ = Which::eValue;
437 template <class... Es>
438 void assignError(Es&&... es) {
439 if (this->which_ == Which::eError) {
440 expected_detail::doEmplaceAssign(
441 0, this->error(), static_cast<Es&&>(es)...);
444 ::new ((void*)std::addressof(this->error()))
445 Error(static_cast<Es&&>(es)...);
446 this->which_ = Which::eError;
449 bool isThis(const ExpectedStorage* that) const {
452 constexpr bool isSelfAssign(const void*) const {
455 template <class Other>
456 void assign(Other&& that) {
457 if (isSelfAssign(&that))
459 switch (that.which_) {
461 this->assignValue(static_cast<Other&&>(that).value());
464 this->assignError(static_cast<Other&&>(that).error());
473 // For small (pointer-sized) trivial types, a struct is faster than a union.
474 template <class Value, class Error>
475 struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
476 using value_type = Value;
477 using error_type = Error;
482 constexpr ExpectedStorage() noexcept
483 : which_(Which::eError), error_(), value_() {}
484 explicit constexpr ExpectedStorage(EmptyTag) noexcept
485 : which_(Which::eEmpty), error_(), value_() {}
486 template <class... Vs>
487 explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
488 noexcept(Value(static_cast<Vs&&>(vs)...)))
489 : which_(Which::eValue), error_(), value_(static_cast<Vs&&>(vs)...) {}
490 template <class... Es>
491 explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
492 noexcept(Error(static_cast<Es&&>(es)...)))
493 : which_(Which::eError), error_(static_cast<Es&&>(es)...), value_() {}
494 void clear() noexcept {}
495 constexpr static bool uninitializedByException() noexcept {
498 template <class... Vs>
499 void assignValue(Vs&&... vs) {
500 expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
501 which_ = Which::eValue;
503 template <class... Es>
504 void assignError(Es&&... es) {
505 expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
506 which_ = Which::eError;
508 template <class Other>
509 void assign(Other&& that) {
510 switch (that.which_) {
512 this->assignValue(static_cast<Other&&>(that).value());
515 this->assignError(static_cast<Other&&>(that).error());
525 const Value& value() const& {
529 return std::move(value_);
534 const Error& error() const& {
538 return std::move(error_);
542 namespace expected_detail_ExpectedHelper {
543 // Tricky hack so that Expected::then can handle lambdas that return void
545 inline T&& operator,(T&& t, Unit) noexcept {
546 return static_cast<T&&>(t);
549 struct ExpectedHelper {
550 template <class Error, class T>
551 static constexpr Expected<T, Error> return_(T t) {
552 return folly::makeExpected<Error>(t);
557 class U FOLLY_REQUIRES_TRAILING(
558 expected_detail::IsConvertible<U&&, Error>::value)>
559 static constexpr Expected<T, Error> return_(Expected<T, U> t) {
563 template <class This>
564 static typename std::decay<This>::type then_(This&& ex) {
565 return static_cast<This&&>(ex);
569 // Don't warn about not using the overloaded comma operator.
570 FOLLY_MSVC_DISABLE_WARNING(4913)
575 class E = ExpectedErrorType<This>,
576 class T = ExpectedHelper>
577 static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
578 T::template return_<E>(
579 (std::declval<Fn>()(std::declval<This>().value()), unit)),
580 std::declval<Fns>()...)) {
581 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
583 T::template return_<E>(
584 // Uses the comma operator defined above IFF the lambda
586 (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
587 static_cast<Fns&&>(fns)...);
588 return makeUnexpected(static_cast<This&&>(ex).error());
595 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
596 class Err = decltype(std::declval<No>()(std::declval<This>().error()))
597 FOLLY_REQUIRES_TRAILING(!std::is_void<Err>::value)>
598 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
599 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
600 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
601 throw static_cast<No&&>(no)(static_cast<This&&>(ex).error());
608 class Ret = decltype(std::declval<Yes>()(std::declval<This>().value())),
609 class Err = decltype(std::declval<No>()(std::declval<This&>().error()))
610 FOLLY_REQUIRES_TRAILING(std::is_void<Err>::value)>
611 static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
612 if (LIKELY(ex.which_ == expected_detail::Which::eValue))
613 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
614 static_cast<No&&>(no)(ex.error());
615 throw typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess()(
616 static_cast<This&&>(ex).error());
621 /* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
623 struct UnexpectedTag {};
625 } // namespace expected_detail
628 expected_detail::UnexpectedTag (&)(expected_detail::UnexpectedTag);
630 inline expected_detail::UnexpectedTag unexpected(
631 expected_detail::UnexpectedTag = {}) {
636 * An exception type thrown by Expected on catastrophic logic errors.
638 class BadExpectedAccess : public std::logic_error {
640 BadExpectedAccess() : std::logic_error("bad Expected access") {}
644 * Unexpected - a helper type used to disambiguate the construction of
645 * Expected objects in the error state.
647 template <class Error>
648 class Unexpected final {
650 friend class Unexpected;
651 template <class V, class E>
652 friend class Expected;
653 friend struct expected_detail::ExpectedHelper;
657 * Unexpected::BadExpectedAccess - An exception type thrown by Expected
658 * when the user tries to access the nested value but the Expected object is
659 * actually storing an error code.
661 class BadExpectedAccess : public folly::BadExpectedAccess {
663 explicit BadExpectedAccess(Error err)
664 : folly::BadExpectedAccess(), error_(std::move(err)) {}
666 * The error code that was held by the Expected object when the user
667 * erroneously requested the value.
669 Error error() const {
680 Unexpected() = default;
681 Unexpected(const Unexpected&) = default;
682 Unexpected(Unexpected&&) = default;
683 Unexpected& operator=(const Unexpected&) = default;
684 Unexpected& operator=(Unexpected&&) = default;
685 constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {}
686 constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {}
688 template <class Other FOLLY_REQUIRES_TRAILING(
689 std::is_constructible<Error, Other&&>::value)>
690 constexpr /* implicit */ Unexpected(Unexpected<Other> that)
691 : error_(std::move(that.error())) {}
696 template <class Other FOLLY_REQUIRES_TRAILING(
697 std::is_assignable<Error&, Other&&>::value)>
698 Unexpected& operator=(Unexpected<Other> that) {
699 error_ = std::move(that.error());
708 const Error& error() const& {
712 return std::move(error_);
716 struct MakeBadExpectedAccess {
718 BadExpectedAccess operator()(E&& err) const {
719 return BadExpectedAccess(static_cast<E&&>(err));
727 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
728 inline bool operator==(
729 const Unexpected<Error>& lhs,
730 const Unexpected<Error>& rhs) {
731 return lhs.error() == rhs.error();
735 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Error>::value)>
736 inline bool operator!=(
737 const Unexpected<Error>& lhs,
738 const Unexpected<Error>& rhs) {
739 return !(lhs == rhs);
743 * For constructing an Unexpected object from an error code. Unexpected objects
744 * are implicitly convertible to Expected object in the error state. Usage is
747 * enum class MyErrorCode { BAD_ERROR, WORSE_ERROR };
748 * Expected<int, MyErrorCode> myAPI() {
750 * return i ? makeExpected<MyErrorCode>(i)
751 * : makeUnexpected(MyErrorCode::BAD_ERROR);
754 template <class Error>
755 constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(
757 return Unexpected<typename std::decay<Error>::type>{
758 static_cast<Error&&>(err)};
762 * Expected - For holding a value or an error. Useful as an alternative to
763 * exceptions, for APIs where throwing on failure would be too expensive.
765 * Expected<Value, Error> is a variant over the types Value and Error.
767 * Expected does not offer support for references. Use
768 * Expected<std::reference_wrapper<T>, Error> if your API needs to return a
769 * reference or an error.
771 * Expected offers a continuation-based interface to reduce the boilerplate
772 * of checking error codes. The Expected::then member function takes a lambda
773 * that is to execute should the Expected object contain a value. The return
774 * value of the lambda is wrapped in an Expected and returned. If the lambda is
775 * not executed because the Expected contains an error, the error is returned
776 * immediately in a new Expected object.
778 * Expected<int, Error> funcTheFirst();
779 * Expected<std::string, Error> funcTheSecond() {
780 * return funcTheFirst().then([](int i) { return std::to_string(i); });
783 * The above line of code could more verbosely written as:
785 * Expected<std::string, Error> funcTheSecond() {
786 * if (auto ex = funcTheFirst()) {
787 * return std::to_string(*ex);
789 * return makeUnexpected(ex.error());
792 * Continuations can chain, like:
794 * Expected<D, Error> maybeD = someFunc()
795 * .then([](A a){return B(a);})
796 * .then([](B b){return C(b);})
797 * .then([](C c){return D(c);});
799 * To avoid the redundant error checking that would happen if a call at the
800 * front of the chain returns an error, these call chains can be collaped into
801 * a single call to .then:
803 * Expected<D, Error> maybeD = someFunc()
804 * .then([](A a){return B(a);},
805 * [](B b){return C(b);},
806 * [](C c){return D(c);});
808 * The result of .then() is wrapped into Expected< ~, Error > if it isn't
809 * of that form already. Consider the following code:
811 * extern Expected<std::string, Error> readLineFromIO();
812 * extern Expected<int, Error> parseInt(std::string);
813 * extern int increment(int);
815 * Expected<int, Error> x = readLineFromIO().then(parseInt).then(increment);
817 * From the code above, we see that .then() works both with functions that
818 * return an Expected< ~, Error > (like parseInt) and with ones that return
819 * a plain value (like increment). In the case of parseInt, .then() returns
820 * the result of parseInt as-is. In the case of increment, it wraps the int
821 * that increment returns into an Expected< int, Error >.
823 * Sometimes when using a continuation you would prefer an exception to be
824 * thrown for a value-less Expected. For that you can use .thenOrThrow, as
828 * .thenOrThrow([](A a){return B(a);});
830 * The above call to thenOrThrow will invoke the lambda if the Expected returned
831 * by someFunc() contains a value. Otherwise, it will throw an exception of type
832 * Unexpected<Error>::BadExpectedAccess. If you prefer it throw an exception of
833 * a different type, you can pass a second lambda to thenOrThrow:
836 * .thenOrThrow([](A a){return B(a);},
837 * [](Error e) {throw MyException(e);});
839 * Like C++17's std::variant, Expected offers the almost-never-empty guarantee;
840 * that is, an Expected<Value, Error> almost always contains either a Value or
841 * and Error. Partially-formed Expected objects occur when an assignment to
842 * an Expected object that would change the type of the contained object (Value-
843 * to-Error or vice versa) throws. Trying to access either the contained value
844 * or error object causes Expected to throw folly::BadExpectedAccess.
846 * Expected models OptionalPointee, so calling 'get_pointer(ex)' will return a
847 * pointer to nullptr if the 'ex' is in the error state, and a pointer to the
850 * Expected<int, Error> maybeInt = ...;
851 * if (int* v = get_pointer(maybeInt)) {
852 * cout << *v << endl;
855 template <class Value, class Error>
856 class Expected final : expected_detail::ExpectedStorage<Value, Error> {
857 template <class, class>
858 friend class Expected;
859 template <class, class, expected_detail::StorageType>
860 friend struct expected_detail::ExpectedStorage;
861 friend struct expected_detail::ExpectedHelper;
862 using Base = expected_detail::ExpectedStorage<Value, Error>;
863 using MakeBadExpectedAccess =
864 typename Unexpected<Error>::MakeBadExpectedAccess;
868 const Base& base() const& {
872 return std::move(*this);
876 using value_type = Value;
877 using error_type = Error;
878 using IsTriviallyCopyable = typename expected_detail::
879 StrictAllOf<IsTriviallyCopyable, Value, Error>::type;
882 using rebind = Expected<U, Error>;
885 !std::is_reference<Value>::value,
886 "Expected may not be used with reference types");
888 !std::is_abstract<Value>::value,
889 "Expected may not be used with abstract types");
894 template <class B = Base, class = decltype(B{})>
895 Expected() noexcept(noexcept(B{})) : Base() {}
896 Expected(const Expected& that) = default;
897 Expected(Expected&& that) = default;
901 class E FOLLY_REQUIRES_TRAILING(
902 !std::is_same<Expected<V, E>, Expected>::value &&
903 std::is_constructible<Value, V&&>::value &&
904 std::is_constructible<Error, E&&>::value)>
905 Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} {
906 *this = std::move(that);
909 FOLLY_REQUIRES(std::is_copy_constructible<Value>::value)
910 constexpr /* implicit */ Expected(const Value& val) noexcept(
911 noexcept(Value(val)))
912 : Base{expected_detail::ValueTag{}, val} {}
914 FOLLY_REQUIRES(std::is_move_constructible<Value>::value)
915 constexpr /* implicit */ Expected(Value&& val) noexcept(
916 noexcept(Value(std::move(val))))
917 : Base{expected_detail::ValueTag{}, std::move(val)} {}
919 template <class T FOLLY_REQUIRES_TRAILING(
920 std::is_convertible<T, Value>::value &&
921 !std::is_convertible<T, Error>::value)>
922 constexpr /* implicit */ Expected(T&& val) noexcept(
923 noexcept(Value(static_cast<T&&>(val))))
924 : Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {}
926 template <class... Ts FOLLY_REQUIRES_TRAILING(
927 std::is_constructible<Value, Ts&&...>::value)>
928 explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
929 noexcept(Value(std::declval<Ts>()...)))
930 : Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {}
934 class... Ts FOLLY_REQUIRES_TRAILING(
935 std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
937 explicit constexpr Expected(
939 std::initializer_list<U> il,
940 Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
941 : Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {}
943 // If overload resolution selects one of these deleted functions, that
944 // means you need to use makeUnexpected
945 /* implicit */ Expected(const Error&) = delete;
946 /* implicit */ Expected(Error&&) = delete;
948 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
949 constexpr Expected(unexpected_t, const Error& err) noexcept(
950 noexcept(Error(err)))
951 : Base{expected_detail::ErrorTag{}, err} {}
953 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
954 constexpr Expected(unexpected_t, Error&& err) noexcept(
955 noexcept(Error(std::move(err))))
956 : Base{expected_detail::ErrorTag{}, std::move(err)} {}
958 FOLLY_REQUIRES(std::is_copy_constructible<Error>::value)
959 constexpr /* implicit */ Expected(const Unexpected<Error>& err) noexcept(
960 noexcept(Error(err.error())))
961 : Base{expected_detail::ErrorTag{}, err.error()} {}
963 FOLLY_REQUIRES(std::is_move_constructible<Error>::value)
964 constexpr /* implicit */ Expected(Unexpected<Error>&& err) noexcept(
965 noexcept(Error(std::move(err.error()))))
966 : Base{expected_detail::ErrorTag{}, std::move(err.error())} {}
969 * Assignment operators
971 Expected& operator=(const Expected& that) = default;
972 Expected& operator=(Expected&& that) = default;
976 class E FOLLY_REQUIRES_TRAILING(
977 !std::is_same<Expected<V, E>, Expected>::value &&
978 expected_detail::IsConvertible<V&&, Value>::value &&
979 expected_detail::IsConvertible<E&&, Error>::value)>
980 Expected& operator=(Expected<V, E> that) {
981 this->assign(std::move(that));
985 FOLLY_REQUIRES(expected_detail::IsCopyable<Value>::value)
986 Expected& operator=(const Value& val) noexcept(
987 expected_detail::IsNothrowCopyable<Value>::value) {
988 this->assignValue(val);
992 FOLLY_REQUIRES(expected_detail::IsMovable<Value>::value)
993 Expected& operator=(Value&& val) noexcept(
994 expected_detail::IsNothrowMovable<Value>::value) {
995 this->assignValue(std::move(val));
999 template <class T FOLLY_REQUIRES_TRAILING(
1000 std::is_convertible<T, Value>::value &&
1001 !std::is_convertible<T, Error>::value)>
1002 Expected& operator=(T&& val) {
1003 this->assignValue(static_cast<T&&>(val));
1007 FOLLY_REQUIRES(expected_detail::IsCopyable<Error>::value)
1008 Expected& operator=(const Unexpected<Error>& err) noexcept(
1009 expected_detail::IsNothrowCopyable<Error>::value) {
1010 this->assignError(err.error());
1014 FOLLY_REQUIRES(expected_detail::IsMovable<Error>::value)
1015 Expected& operator=(Unexpected<Error>&& err) noexcept(
1016 expected_detail::IsNothrowMovable<Error>::value) {
1017 this->assignError(std::move(err.error()));
1021 template <class... Ts FOLLY_REQUIRES_TRAILING(
1022 std::is_constructible<Value, Ts&&...>::value)>
1023 void emplace(Ts&&... ts) {
1024 this->assignValue(static_cast<Ts&&>(ts)...);
1030 void swap(Expected& that) noexcept(
1031 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1032 if (this->uninitializedByException() || that.uninitializedByException())
1033 throw BadExpectedAccess();
1037 swap(this->value_, that.value_);
1039 Error e(std::move(that.error_));
1040 that.assignValue(std::move(this->value_));
1041 this->assignError(std::move(e));
1045 swap(this->error_, that.error_);
1047 Error e(std::move(this->error_));
1048 this->assignValue(std::move(that.value_));
1049 that.assignError(std::move(e));
1054 // If overload resolution selects one of these deleted functions, that
1055 // means you need to use makeUnexpected
1056 /* implicit */ Expected& operator=(const Error&) = delete;
1057 /* implicit */ Expected& operator=(Error&&) = delete;
1060 * Relational Operators
1062 template <class Val, class Err>
1063 friend typename std::enable_if<IsEqualityComparable<Val>::value, bool>::type
1064 operator==(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1065 template <class Val, class Err>
1066 friend typename std::enable_if<IsLessThanComparable<Val>::value, bool>::type
1067 operator<(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
1072 constexpr bool hasValue() const noexcept {
1073 return expected_detail::Which::eValue == this->which_;
1076 constexpr bool hasError() const noexcept {
1077 return expected_detail::Which::eError == this->which_;
1080 using Base::uninitializedByException;
1082 const Value& value() const& {
1084 return this->Base::value();
1089 return this->Base::value();
1092 Value&& value() && {
1094 return std::move(this->Base::value());
1097 const Error& error() const& {
1099 return this->Base::error();
1104 return this->Base::error();
1107 Error&& error() && {
1109 return std::move(this->Base::error());
1112 // Return a copy of the value if set, or a given default if not.
1114 Value value_or(U&& dflt) const& {
1115 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1116 return this->value_;
1118 return static_cast<U&&>(dflt);
1122 Value value_or(U&& dflt) && {
1123 if (LIKELY(this->which_ == expected_detail::Which::eValue)) {
1124 return std::move(this->value_);
1126 return static_cast<U&&>(dflt);
1129 explicit constexpr operator bool() const noexcept {
1133 const Value& operator*() const& {
1134 return this->value();
1137 Value& operator*() & {
1138 return this->value();
1141 Value&& operator*() && {
1142 return std::move(this->value());
1145 const Value* operator->() const {
1146 return std::addressof(this->value());
1149 Value* operator->() {
1150 return std::addressof(this->value());
1153 const Value* get_pointer() const& noexcept {
1154 return hasValue() ? std::addressof(this->value_) : nullptr;
1157 Value* get_pointer() & noexcept {
1158 return hasValue() ? std::addressof(this->value_) : nullptr;
1161 Value* get_pointer() && = delete;
1166 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1167 auto then(Fns&&... fns) const& -> decltype(
1168 expected_detail::ExpectedHelper::then_(
1169 std::declval<const Base&>(),
1170 std::declval<Fns>()...)) {
1171 if (this->uninitializedByException())
1172 throw BadExpectedAccess();
1173 return expected_detail::ExpectedHelper::then_(
1174 base(), static_cast<Fns&&>(fns)...);
1177 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1178 auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1179 std::declval<Base&>(),
1180 std::declval<Fns>()...)) {
1181 if (this->uninitializedByException())
1182 throw BadExpectedAccess();
1183 return expected_detail::ExpectedHelper::then_(
1184 base(), static_cast<Fns&&>(fns)...);
1187 template <class... Fns FOLLY_REQUIRES_TRAILING(sizeof...(Fns) >= 1)>
1188 auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1189 std::declval<Base&&>(),
1190 std::declval<Fns>()...)) {
1191 if (this->uninitializedByException())
1192 throw BadExpectedAccess();
1193 return expected_detail::ExpectedHelper::then_(
1194 std::move(base()), static_cast<Fns&&>(fns)...);
1200 template <class Yes, class No = MakeBadExpectedAccess>
1201 auto thenOrThrow(Yes&& yes, No&& no = No()) const& -> decltype(
1202 std::declval<Yes>()(std::declval<const Value&>())) {
1203 using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1204 if (this->uninitializedByException())
1205 throw BadExpectedAccess();
1206 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1207 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1210 template <class Yes, class No = MakeBadExpectedAccess>
1211 auto thenOrThrow(Yes&& yes, No&& no = No()) & -> decltype(
1212 std::declval<Yes>()(std::declval<Value&>())) {
1213 using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1214 if (this->uninitializedByException())
1215 throw BadExpectedAccess();
1216 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1217 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1220 template <class Yes, class No = MakeBadExpectedAccess>
1221 auto thenOrThrow(Yes&& yes, No&& no = No()) && -> decltype(
1222 std::declval<Yes>()(std::declval<Value&&>())) {
1223 using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1224 if (this->uninitializedByException())
1225 throw BadExpectedAccess();
1226 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1227 std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1231 void requireValue() const {
1232 if (UNLIKELY(!hasValue())) {
1233 if (LIKELY(hasError()))
1234 throw typename Unexpected<Error>::BadExpectedAccess(this->error_);
1235 throw BadExpectedAccess();
1239 void requireError() const {
1240 if (UNLIKELY(!hasError())) {
1241 throw BadExpectedAccess();
1245 expected_detail::Which which() const noexcept {
1246 return this->which_;
1250 template <class Value, class Error>
1251 inline typename std::enable_if<IsEqualityComparable<Value>::value, bool>::type
1253 const Expected<Value, Error>& lhs,
1254 const Expected<Value, Error>& rhs) {
1255 if (UNLIKELY(lhs.which_ != rhs.which_))
1256 return UNLIKELY(lhs.uninitializedByException()) ? false
1257 : throw BadExpectedAccess();
1258 if (UNLIKELY(lhs.uninitializedByException()))
1259 throw BadExpectedAccess();
1260 if (UNLIKELY(lhs.hasError()))
1261 return true; // All error states are considered equal
1262 return lhs.value_ == rhs.value_;
1267 class Error FOLLY_REQUIRES_TRAILING(IsEqualityComparable<Value>::value)>
1268 inline bool operator!=(
1269 const Expected<Value, Error>& lhs,
1270 const Expected<Value, Error>& rhs) {
1271 return !(rhs == lhs);
1274 template <class Value, class Error>
1275 inline typename std::enable_if<IsLessThanComparable<Value>::value, bool>::type
1277 const Expected<Value, Error>& lhs,
1278 const Expected<Value, Error>& rhs) {
1280 lhs.uninitializedByException() || rhs.uninitializedByException()))
1281 throw BadExpectedAccess();
1282 if (UNLIKELY(lhs.hasError()))
1283 return !rhs.hasError();
1284 if (UNLIKELY(rhs.hasError()))
1286 return lhs.value_ < rhs.value_;
1291 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1292 inline bool operator<=(
1293 const Expected<Value, Error>& lhs,
1294 const Expected<Value, Error>& rhs) {
1295 return !(rhs < lhs);
1300 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1301 inline bool operator>(
1302 const Expected<Value, Error>& lhs,
1303 const Expected<Value, Error>& rhs) {
1309 class Error FOLLY_REQUIRES_TRAILING(IsLessThanComparable<Value>::value)>
1310 inline bool operator>=(
1311 const Expected<Value, Error>& lhs,
1312 const Expected<Value, Error>& rhs) {
1313 return !(lhs < rhs);
1317 * swap Expected values
1319 template <class Error, class Value>
1320 void swap(Expected<Error, Value>& lhs, Expected<Value, Error>& rhs) noexcept(
1321 expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
1325 template <class Value, class Error>
1326 const Value* get_pointer(const Expected<Value, Error>& ex) noexcept {
1327 return ex.get_pointer();
1330 template <class Value, class Error>
1331 Value* get_pointer(Expected<Value, Error>& ex) noexcept {
1332 return ex.get_pointer();
1336 * For constructing an Expected object from a value, with the specified
1337 * Error type. Usage is as follows:
1339 * enum MyErrorCode { BAD_ERROR, WORSE_ERROR };
1340 * Expected<int, MyErrorCode> myAPI() {
1342 * return i ? makeExpected<MyErrorCode>(i) : makeUnexpected(BAD_ERROR);
1345 template <class Error, class Value>
1346 constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
1348 return Expected<typename std::decay<Value>::type, Error>{
1349 in_place, static_cast<Value&&>(val)};
1352 // Suppress comparability of Optional<T> with T, despite implicit conversion.
1353 template <class Value, class Error>
1354 bool operator==(const Expected<Value, Error>&, const Value& other) = delete;
1355 template <class Value, class Error>
1356 bool operator!=(const Expected<Value, Error>&, const Value& other) = delete;
1357 template <class Value, class Error>
1358 bool operator<(const Expected<Value, Error>&, const Value& other) = delete;
1359 template <class Value, class Error>
1360 bool operator<=(const Expected<Value, Error>&, const Value& other) = delete;
1361 template <class Value, class Error>
1362 bool operator>=(const Expected<Value, Error>&, const Value& other) = delete;
1363 template <class Value, class Error>
1364 bool operator>(const Expected<Value, Error>&, const Value& other) = delete;
1365 template <class Value, class Error>
1366 bool operator==(const Value& other, const Expected<Value, Error>&) = delete;
1367 template <class Value, class Error>
1368 bool operator!=(const Value& other, const Expected<Value, Error>&) = delete;
1369 template <class Value, class Error>
1370 bool operator<(const Value& other, const Expected<Value, Error>&) = delete;
1371 template <class Value, class Error>
1372 bool operator<=(const Value& other, const Expected<Value, Error>&) = delete;
1373 template <class Value, class Error>
1374 bool operator>=(const Value& other, const Expected<Value, Error>&) = delete;
1375 template <class Value, class Error>
1376 bool operator>(const Value& other, const Expected<Value, Error>&) = delete;
1378 } // namespace folly
1380 #if defined(__GNUC__) && !defined(__clang__)
1381 #pragma GCC diagnostic pop
1384 #undef FOLLY_REQUIRES
1385 #undef FOLLY_REQUIRES_TRAILING