*/
/**
- * Like folly::Optional, but can store a value *or* and error.
+ * Like folly::Optional, but can store a value *or* an error.
*
* @author Eric Niebler (eniebler@fb.com)
*/
#include <folly/Likely.h>
#include <folly/Portability.h>
#include <folly/Preprocessor.h>
-#include <folly/Traits.h> // for in_place_t
+#include <folly/Traits.h>
#include <folly/Unit.h>
+#include <folly/Utility.h>
#define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__)
}
template <class Other>
void assign(Other&& that) {
- if (isSelfAssign(&that))
+ if (isSelfAssign(&that)) {
return;
+ }
switch (that.which_) {
case Which::eValue:
this->assignValue(static_cast<Other&&>(that).value());
T::template return_<E>(
(std::declval<Fn>()(std::declval<This>().value()), unit)),
std::declval<Fns>()...)) {
- if (LIKELY(ex.which_ == expected_detail::Which::eValue))
+ if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
return T::then_(
T::template return_<E>(
// Uses the comma operator defined above IFF the lambda
// returns non-void.
(static_cast<Fn&&>(fn)(static_cast<This&&>(ex).value()), unit)),
static_cast<Fns&&>(fns)...);
+ }
return makeUnexpected(static_cast<This&&>(ex).error());
}
class Err = decltype(std::declval<No>()(std::declval<This>().error()))
FOLLY_REQUIRES_TRAILING(!std::is_void<Err>::value)>
static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
- if (LIKELY(ex.which_ == expected_detail::Which::eValue))
+ if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
+ }
throw static_cast<No&&>(no)(static_cast<This&&>(ex).error());
}
class Err = decltype(std::declval<No>()(std::declval<This&>().error()))
FOLLY_REQUIRES_TRAILING(std::is_void<Err>::value)>
static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
- if (LIKELY(ex.which_ == expected_detail::Which::eValue))
+ if (LIKELY(ex.which_ == expected_detail::Which::eValue)) {
return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
+ }
static_cast<No&&>(no)(ex.error());
throw typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess()(
static_cast<This&&>(ex).error());
}
FOLLY_POP_WARNING
};
-}
+} // namespace expected_detail_ExpectedHelper
/* using override */ using expected_detail_ExpectedHelper::ExpectedHelper;
struct UnexpectedTag {};
*/
void swap(Expected& that) noexcept(
expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
- if (this->uninitializedByException() || that.uninitializedByException())
+ if (this->uninitializedByException() || that.uninitializedByException()) {
throw BadExpectedAccess();
+ }
using std::swap;
if (*this) {
if (that) {
expected_detail::ExpectedHelper::then_(
std::declval<const Base&>(),
std::declval<Fns>()...)) {
- if (this->uninitializedByException())
+ if (this->uninitializedByException()) {
throw BadExpectedAccess();
+ }
return expected_detail::ExpectedHelper::then_(
base(), static_cast<Fns&&>(fns)...);
}
auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
std::declval<Base&>(),
std::declval<Fns>()...)) {
- if (this->uninitializedByException())
+ if (this->uninitializedByException()) {
throw BadExpectedAccess();
+ }
return expected_detail::ExpectedHelper::then_(
base(), static_cast<Fns&&>(fns)...);
}
auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
std::declval<Base&&>(),
std::declval<Fns>()...)) {
- if (this->uninitializedByException())
+ if (this->uninitializedByException()) {
throw BadExpectedAccess();
+ }
return expected_detail::ExpectedHelper::then_(
std::move(base()), static_cast<Fns&&>(fns)...);
}
auto thenOrThrow(Yes&& yes, No&& no = No{}) const& -> decltype(
std::declval<Yes>()(std::declval<const Value&>())) {
using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
- if (this->uninitializedByException())
+ if (this->uninitializedByException()) {
throw BadExpectedAccess();
+ }
return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
}
auto thenOrThrow(Yes&& yes, No&& no = No{}) & -> decltype(
std::declval<Yes>()(std::declval<Value&>())) {
using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
- if (this->uninitializedByException())
+ if (this->uninitializedByException()) {
throw BadExpectedAccess();
+ }
return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
}
auto thenOrThrow(Yes&& yes, No&& no = No{}) && -> decltype(
std::declval<Yes>()(std::declval<Value&&>())) {
using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
- if (this->uninitializedByException())
+ if (this->uninitializedByException()) {
throw BadExpectedAccess();
+ }
return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
}
private:
void requireValue() const {
if (UNLIKELY(!hasValue())) {
- if (LIKELY(hasError()))
+ if (LIKELY(hasError())) {
throw typename Unexpected<Error>::BadExpectedAccess(this->error_);
+ }
throw BadExpectedAccess();
}
}
operator==(
const Expected<Value, Error>& lhs,
const Expected<Value, Error>& rhs) {
- if (UNLIKELY(lhs.which_ != rhs.which_))
+ if (UNLIKELY(lhs.which_ != rhs.which_)) {
return UNLIKELY(lhs.uninitializedByException()) ? false
: throw BadExpectedAccess();
- if (UNLIKELY(lhs.uninitializedByException()))
+ }
+ if (UNLIKELY(lhs.uninitializedByException())) {
throw BadExpectedAccess();
- if (UNLIKELY(lhs.hasError()))
+ }
+ if (UNLIKELY(lhs.hasError())) {
return true; // All error states are considered equal
+ }
return lhs.value_ == rhs.value_;
}
const Expected<Value, Error>& lhs,
const Expected<Value, Error>& rhs) {
if (UNLIKELY(
- lhs.uninitializedByException() || rhs.uninitializedByException()))
+ lhs.uninitializedByException() || rhs.uninitializedByException())) {
throw BadExpectedAccess();
- if (UNLIKELY(lhs.hasError()))
+ }
+ if (UNLIKELY(lhs.hasError())) {
return !rhs.hasError();
- if (UNLIKELY(rhs.hasError()))
+ }
+ if (UNLIKELY(rhs.hasError())) {
return false;
+ }
return lhs.value_ < rhs.value_;
}