25 #include <initializer_list> 28 #include <type_traits> 43 #define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__) 45 #define FOLLY_REQUIRES_IMPL(...) \ 46 bool FOLLY_EXPECTED_ID(Requires) = false, \ 47 typename std::enable_if< \ 48 (FOLLY_EXPECTED_ID(Requires) || static_cast<bool>(__VA_ARGS__)), \ 51 #define FOLLY_REQUIRES_TRAILING(...) , FOLLY_REQUIRES_IMPL(__VA_ARGS__) 53 #define FOLLY_REQUIRES(...) template <FOLLY_REQUIRES_IMPL(__VA_ARGS__)> 59 #if defined(__GNUC__) && !defined(__clang__) 60 #pragma GCC diagnostic push 61 #pragma GCC diagnostic ignored "-Wuninitialized" 62 #pragma GCC diagnostic ignored "-Wpragmas" 63 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 71 template <
class Error>
74 template <
class Error>
77 template <
class Value,
class Error>
80 template <
class Error,
class Value>
87 template <
class Expected>
89 typename std::remove_reference<Expected>::type::value_type;
94 template <
class Expected>
96 typename std::remove_reference<Expected>::type::error_type;
99 namespace expected_detail {
101 template <
typename Value,
typename Error>
107 template <
template <
class...>
class Trait,
class... Ts>
108 using StrictAllOf = std::conjunction<Trait<Ts>...>;
110 template <
template <
class...>
class Trait,
class... Ts>
116 std::is_copy_constructible<T>,
117 std::is_copy_assignable<T>>;
121 std::is_move_constructible<T>,
122 std::is_move_assignable<T>>;
126 std::is_nothrow_copy_constructible<T>,
127 std::is_nothrow_copy_assignable<T>>;
131 std::is_nothrow_move_constructible<T>,
132 std::is_nothrow_move_assignable<T>>;
134 template <
class From,
class To>
136 std::is_constructible<To, From>,
137 std::is_assignable<To&, From>>;
139 template <
class T,
class U>
141 -> decltype(
void(
t = static_cast<U&&>(u))) {
142 t =
static_cast<U&&
>(u);
145 template <
class T,
class U>
147 -> decltype(
void(
T(static_cast<U&&>(u)))) {
149 ::new ((
void*)std::addressof(
t))
T(static_cast<U&&>(u));
152 template <
class T,
class... Us>
154 -> decltype(
void(
t =
T(static_cast<Us&&>(
us)...))) {
155 t =
T(static_cast<Us&&>(
us)...);
158 template <
class T,
class... Us>
160 -> decltype(
void(
T(static_cast<Us&&>(
us)...))) {
162 ::new ((
void*)std::addressof(
t))
T(static_cast<Us&&>(
us)...);
171 template <
class Value,
class Error>
174 ? (
sizeof(std::pair<Value, Error>) <=
sizeof(
void * [2]) &&
184 StorageType = expected_detail::getStorageType<Value, Error>()>
195 template <
class E = Error,
class = decltype(
E{})>
200 template <
class... Vs>
202 noexcept(Value(static_cast<Vs&&>(vs)...)))
203 : value_(static_cast<Vs&&>(vs)...), which_(
Which::
eValue) {}
204 template <
class... Es>
206 noexcept(Error(static_cast<Es&&>(es)...)))
207 : error_(static_cast<Es&&>(es)...), which_(
Which::eError) {}
214 template <
class... Vs>
219 template <
class... Es>
224 template <
class Other>
226 switch (that.which_) {
228 this->assignValue(static_cast<Other&&>(that).
value());
231 this->assignError(static_cast<Other&&>(that).
error());
264 template <
class Value,
class Error>
274 template <
class... Vs>
276 noexcept(Value(static_cast<Vs&&>(vs)...)))
277 : value_(static_cast<Vs&&>(vs)...), which_(
Which::
eValue) {}
278 template <
class... Es>
280 noexcept(Error(static_cast<Es&&>(es)...)))
281 : error_(static_cast<Es&&>(es)...), which_(
Which::eError) {}
311 template <
class Derived,
bool,
bool Noexcept>
315 static_cast<Derived*
>(
this)->assign(static_cast<const Derived&>(that));
322 template <
class Derived,
bool Noexcept>
331 template <
class Derived,
bool,
bool Noexcept>
336 static_cast<Derived*
>(
this)->assign(
std::move(static_cast<Derived&>(that)));
342 template <
class Derived,
bool Noexcept>
351 template <
class Derived,
bool,
bool Noexcept>
357 static_cast<Derived*
>(
this)->assign(static_cast<const Derived&>(that));
363 template <
class Derived,
bool Noexcept>
372 template <
class Derived,
bool,
bool Noexcept>
379 static_cast<Derived*
>(
this)->assign(
std::move(static_cast<Derived&>(that)));
384 template <
class Derived,
bool Noexcept>
393 template <
class Value,
class Error>
397 ExpectedStorage<Value, Error, StorageType::eUnion>,
398 StrictAllOf<std::is_copy_constructible, Value, Error>::value,
399 StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::value>,
401 ExpectedStorage<Value, Error, StorageType::eUnion>,
402 StrictAllOf<std::is_move_constructible, Value, Error>::value,
403 StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::value>,
405 ExpectedStorage<Value, Error, StorageType::eUnion>,
406 StrictAllOf<IsCopyable, Value, Error>::value,
407 StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
409 ExpectedStorage<Value, Error, StorageType::eUnion>,
410 StrictAllOf<IsMovable, Value, Error>::value,
411 StrictAllOf<IsNothrowMovable, Value, Error>::value> {
415 template <
class E = Error,
class = decltype(
E{})>
426 switch (this->which_) {
428 this->
value().~Value();
431 this->
error().~Error();
441 template <
class... Vs>
445 0, this->
value(), static_cast<Vs&&>(vs)...);
448 ::new ((
void*)std::addressof(this->
value()))
449 Value(static_cast<Vs&&>(vs)...);
453 template <
class... Es>
457 0, this->
error(), static_cast<Es&&>(es)...);
460 ::new ((
void*)std::addressof(this->
error()))
461 Error(static_cast<Es&&>(es)...);
471 template <
class Other>
473 if (isSelfAssign(&that)) {
476 switch (that.which_) {
478 this->assignValue(static_cast<Other&&>(that).
value());
481 this->assignError(static_cast<Other&&>(that).
error());
491 template <
class Value,
class Error>
500 : which_(
Which::eError), error_{}, value_{} {}
503 template <
class... Vs>
505 noexcept(Value(static_cast<Vs&&>(vs)...)))
506 : which_(
Which::
eValue), error_{}, value_(static_cast<Vs&&>(vs)...) {}
507 template <
class... Es>
509 noexcept(Error(static_cast<Es&&>(es)...)))
510 : which_(
Which::eError), error_(static_cast<Es&&>(es)...), value_{} {}
515 template <
class... Vs>
520 template <
class... Es>
525 template <
class Other>
527 switch (that.which_) {
529 this->assignValue(static_cast<Other&&>(that).
value());
532 this->assignError(static_cast<Other&&>(that).
error());
565 namespace expected_detail_ExpectedHelper {
569 return static_cast<T&&
>(
t);
573 template <
class Error,
class T>
575 return folly::makeExpected<Error>(
t);
586 template <
class This>
588 return static_cast<This&&
>(ex);
600 static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
601 T::template return_<E>(
602 (std::declval<Fn>()(std::declval<This>().
value()),
unit)),
603 std::declval<Fns>()...)) {
606 T::template return_<E>(
609 (static_cast<Fn&&>(fn)(static_cast<This&&>(ex).
value()),
unit)),
610 static_cast<Fns&&>(fns)...);
619 class Ret = decltype(std::declval<Yes>()(std::declval<This>().
value())),
620 class Err = decltype(std::declval<No>()(std::declval<This>().
error()))
624 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).
value()));
633 class Ret = decltype(std::declval<Yes>()(std::declval<This>().
value())),
634 class Err = decltype(std::declval<No>()(std::declval<This&>().
error()))
638 return Ret(static_cast<Yes&&>(yes)(static_cast<This&&>(ex).
value()));
640 static_cast<No&&
>(no)(ex.error());
669 namespace expected_detail {
677 template <
class Error>
681 template <
class V,
class E>
683 friend struct expected_detail::ExpectedHelper;
769 return !(lhs ==
rhs);
784 template <
class Error>
788 static_cast<Error&&
>(err)};
885 template <
class Value,
class Error>
887 template <
class,
class>
889 template <
class,
class, expected_detail::StorageType>
891 friend struct expected_detail::ExpectedHelper;
914 "Expected may not be used with reference types");
917 "Expected may not be used with abstract types");
922 template <
class B =
Base,
class = decltype(
B{})>
963 std::is_constructible<Value, std::initializer_list<U>&, Ts&&...>::
967 std::initializer_list<U> il,
1016 this->assignValue(
val);
1031 this->assignValue(static_cast<T&&>(
val));
1038 this->assignError(err.error());
1045 this->assignError(
std::move(err.error()));
1052 p.promise_->
value_ =
this;
1058 this->assignValue(static_cast<Ts&&>(ts)...);
1066 if (this->uninitializedByException() || that.uninitializedByException()) {
1067 throw_exception<BadExpectedAccess>();
1072 swap(this->value_, that.value_);
1075 that.assignValue(
std::move(this->value_));
1080 swap(this->error_, that.error_);
1083 this->assignValue(
std::move(that.value_));
1091 Expected& operator=(
const Error&) =
delete;
1092 Expected& operator=(Error&&) =
delete;
1097 template <
class Val,
class Err>
1100 template <
class Val,
class Err>
1115 using Base::uninitializedByException;
1151 return this->value_;
1153 return static_cast<U&&
>(dflt);
1161 return static_cast<U&&
>(dflt);
1169 return this->
value();
1173 return this->
value();
1181 return std::addressof(this->
value());
1185 return std::addressof(this->
value());
1189 return hasValue() ? std::addressof(this->value_) :
nullptr;
1193 return hasValue() ? std::addressof(this->value_) :
nullptr;
1203 expected_detail::ExpectedHelper::then_(
1205 std::declval<Fns>()...)) {
1206 if (this->uninitializedByException()) {
1207 throw_exception<BadExpectedAccess>();
1209 return expected_detail::ExpectedHelper::then_(
1210 base(), static_cast<Fns&&>(fns)...);
1214 auto then(Fns&&... fns) & -> decltype(expected_detail::ExpectedHelper::then_(
1215 std::declval<Base&>(),
1216 std::declval<Fns>()...)) {
1217 if (this->uninitializedByException()) {
1218 throw_exception<BadExpectedAccess>();
1220 return expected_detail::ExpectedHelper::then_(
1221 base(), static_cast<Fns&&>(fns)...);
1225 auto then(Fns&&... fns) && -> decltype(expected_detail::ExpectedHelper::then_(
1226 std::declval<Base&&>(),
1227 std::declval<Fns>()...)) {
1228 if (this->uninitializedByException()) {
1229 throw_exception<BadExpectedAccess>();
1231 return expected_detail::ExpectedHelper::then_(
1232 std::move(base()), static_cast<Fns&&>(fns)...);
1238 template <
class Yes,
class No = MakeBadExpectedAccess>
1240 std::declval<Yes>()(std::declval<const Value&>())) {
1241 using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
1242 if (this->uninitializedByException()) {
1243 throw_exception<BadExpectedAccess>();
1245 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1246 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1249 template <
class Yes,
class No = MakeBadExpectedAccess>
1251 std::declval<Yes>()(std::declval<Value&>())) {
1252 using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
1253 if (this->uninitializedByException()) {
1254 throw_exception<BadExpectedAccess>();
1256 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1257 base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1260 template <
class Yes,
class No = MakeBadExpectedAccess>
1262 std::declval<Yes>()(std::declval<Value&&>())) {
1263 using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
1264 if (this->uninitializedByException()) {
1265 throw_exception<BadExpectedAccess>();
1267 return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
1268 std::move(base()), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
1274 if (
LIKELY(hasError())) {
1276 throw_exception<Err>(this->error_);
1278 throw_exception<BadExpectedAccess>();
1284 throw_exception<BadExpectedAccess>();
1289 return this->which_;
1293 template <
class Value,
class Error>
1299 throw_exception<BadExpectedAccess>();
1316 return !(rhs == lhs);
1319 template <
class Value,
class Error>
1326 throw_exception<BadExpectedAccess>();
1343 return !(rhs < lhs);
1361 return !(lhs <
rhs);
1367 template <
class Value,
class Error>
1373 template <
class Value,
class Error>
1375 return ex.get_pointer();
1378 template <
class Value,
class Error>
1380 return ex.get_pointer();
1393 template <
class Error,
class Value>
1396 return Expected<typename std::decay<Value>::type, Error>{
1401 template <
class Value,
class Error>
1403 template <
class Value,
class Error>
1405 template <
class Value,
class Error>
1406 bool operator<(const Expected<Value, Error>&,
const Value& other) =
delete;
1407 template <
class Value,
class Error>
1408 bool operator<=(const Expected<Value, Error>&,
const Value& other) =
delete;
1409 template <
class Value,
class Error>
1411 template <
class Value,
class Error>
1413 template <
class Value,
class Error>
1415 template <
class Value,
class Error>
1417 template <
class Value,
class Error>
1418 bool operator<(const Value& other, const Expected<Value, Error>&) =
delete;
1419 template <
class Value,
class Error>
1420 bool operator<=(const Value& other, const Expected<Value, Error>&) =
delete;
1421 template <
class Value,
class Error>
1423 template <
class Value,
class Error>
1428 #if defined(__GNUC__) && !defined(__clang__) 1429 #pragma GCC diagnostic pop 1432 #undef FOLLY_REQUIRES 1433 #undef FOLLY_REQUIRES_TRAILING 1437 #if FOLLY_HAS_COROUTINES 1438 #include <experimental/coroutine> 1441 namespace expected_detail {
1442 template <
typename Value,
typename Error>
1445 template <
typename Value,
typename Error>
1446 struct PromiseReturn {
1451 promise_->value_ = &storage_;
1453 PromiseReturn(PromiseReturn&& that)
noexcept 1454 : PromiseReturn{*that.promise_} {}
1461 template <
typename Value,
typename Error>
1470 PromiseReturn<Value, Error> get_return_object()
noexcept {
1473 std::experimental::suspend_never initial_suspend()
const noexcept {
1476 std::experimental::suspend_never final_suspend()
const {
1479 template <
typename U>
1480 void return_value(U&& u) {
1481 value_->
emplace(static_cast<U&&>(u));
1483 void unhandled_exception() {
1490 template <
typename Value,
typename Error>
1496 bool await_ready()
const noexcept {
1499 Value await_resume() {
1504 template <
typename U>
1513 template <
typename Value,
typename Error>
1514 expected_detail::Awaitable<Value, Error>
1516 return expected_detail::Awaitable<Value, Error>{
std::move(o)};
1522 namespace experimental {
1523 template <
typename Value,
typename Error,
typename...
Args>
1524 struct coroutine_traits<folly::
Expected<Value, Error>,
Args...> {
1525 using promise_type = folly::expected_detail::Promise<Value, Error>;
1529 #endif // FOLLY_HAS_COROUTINES void assignValue(Vs &&...vs)
constexpr bool hasValue() const noexcept
constexpr ExpectedStorage(ValueTag, Vs &&...vs) noexcept(noexcept(Value(static_cast< Vs && >(vs)...)))
bool operator>(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
#define FOLLY_POP_WARNING
const Base & base() const &
void swap(Expected &that) noexcept(expected_detail::StrictAllOf< IsNothrowSwappable, Value, Error >::value)
constexpr ExpectedStorage(EmptyTag) noexcept
StrictConjunction< std::is_nothrow_copy_constructible< T >, std::is_nothrow_copy_assignable< T >> IsNothrowCopyable
void assignError(Es &&...es)
static Ret thenOrThrow_(This &&ex, Yes &&yes, No &&no)
void requireError() const
ExpectedUnion(ExpectedUnion &&) noexcept
bool uninitializedByException() const noexcept
ExpectedUnion & operator=(ExpectedUnion &&) noexcept
#define FOLLY_PUSH_WARNING
constexpr Expected(in_place_t, std::initializer_list< U > il, Ts &&...ts) noexcept(noexcept(Value(std::declval< Ts >()...)))
void assign(Other &&that)
void requireValue() const
Expected & operator=(T &&val)
auto then(Fns &&...fns)&&-> decltype(expected_detail::ExpectedHelper::then_(std::declval< Base && >(), std::declval< Fns >()...))
CopyConstructible(const CopyConstructible &that) noexcept(Noexcept)
Expected() noexcept(noexcept(B{}))
const Value & value() const &
void assign(Other &&that)
constexpr detail::Map< Move > move
Expected(const expected_detail::PromiseReturn< Value, Error > &p)
void assign(Other &&that)
constexpr Expected(T &&val) noexcept(noexcept(Value(static_cast< T && >(val))))
constexpr Unexpected(const Error &err)
constexpr ExpectedUnion(ErrorTag, Es &&...es) noexcept(noexcept(Error(static_cast< Es && >(es)...)))
static constexpr Expected< T, Error > return_(T t)
const Value * get_pointer() const &noexcept
constexpr Expected< typename std::decay< Value >::type, Error > makeExpected(Value &&)
const Value & value() const &
static FOLLY_PUSH_WARNING auto then_(This &&ex, Fn &&fn, Fns &&...fns) -> decltype(T::then_(T::template return_< E >((std::declval< Fn >()(std::declval< This >().value()), unit)), std::declval< Fns >()...))
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
void assignError(Es &&...es)
—— Concurrent Priority Queue Implementation ——
const Value * operator->() const
in_place_tag in_place(in_place_tag={})
requires E e noexcept(noexcept(s.error(std::move(e))))
BadExpectedAccess operator()(E &&err) const
in_place_tag(&)(in_place_tag) in_place_t
constexpr ExpectedStorage(ValueTag, Vs &&...vs) noexcept(noexcept(Value(static_cast< Vs && >(vs)...)))
CopyAssignable & operator=(const CopyAssignable &that) noexcept(Noexcept)
constexpr ExpectedUnion(EmptyTag) noexcept
requires And< SemiMovable< VN >... > &&SemiMovable< E > auto error(E e)
constexpr bool hasError() const noexcept
static constexpr bool uninitializedByException() noexcept
StrictConjunction< std::is_nothrow_move_constructible< T >, std::is_nothrow_move_assignable< T >> IsNothrowMovable
constexpr Unexpected(Error &&err)
typename std::remove_reference< Expected >::type::value_type ExpectedValueType
FOLLY_PUSH_WARNING RHS rhs
const Error & error() const &
constexpr Expected(in_place_t, Ts &&...ts) noexcept(noexcept(Value(std::declval< Ts >()...)))
Value * get_pointer()&noexcept
constexpr StorageType getStorageType()
Value value_or(U &&dflt) const &
auto doEmplaceAssign(int, T &t, U &&u) -> decltype(void(t=static_cast< U && >(u)))
ExpectedUnion(const ExpectedUnion &)
const Value & value() const &
bool operator!=(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
constexpr ExpectedStorage() noexcept
constexpr ExpectedStorage() noexcept(noexcept(E{}))
#define FOLLY_MSVC_DISABLE_WARNING(warningNumber)
FOLLY_PUSH_WARNING FOLLY_MSVC_DISABLE_WARNING(4702) Error &error()&
const Error & error() const &
MoveAssignable & operator=(MoveAssignable &&that) noexcept(Noexcept)
bool Value(const T &value, M matcher)
constexpr Unexpected< typename std::decay< Error >::type > makeUnexpected(Error &&)
auto then(Fns &&...fns)&-> decltype(expected_detail::ExpectedHelper::then_(std::declval< Base & >(), std::declval< Fns >()...))
expected_detail::Which which() const noexcept
void swap(Expected< Value, Error > &lhs, Expected< Value, Error > &rhs) noexcept(expected_detail::StrictAllOf< IsNothrowSwappable, Value, Error >::value)
bool isSelfAssign(const ExpectedStorage *that) const
expected_detail::UnexpectedTag unexpected(expected_detail::UnexpectedTag={})
void assignValue(Vs &&...vs)
ExpectedUnion & operator=(const ExpectedUnion &)
typename Unexpected< E >::MakeBadExpectedAccess MakeBadExpectedAccess
static std::decay< This >::type then_(This &&ex)
#define FOLLY_REQUIRES(...)
const Error & error() const &
AtomicCounter< T, DeterministicAtomic > Base
constexpr ExpectedStorage() noexcept(noexcept(E{}))
auto thenOrThrow(Yes &&yes, No &&no=No{})&-> decltype(std::declval< Yes >()(std::declval< Value & >()))
const Value & value() const &
static const char *const value
Value & emplace(Args &&...args)
void assignError(Es &&...es)
Unexpected & operator=(Unexpected< Other > that)
BadExpectedAccess(Error err)
constexpr ExpectedUnion(ValueTag, Vs &&...vs) noexcept(noexcept(Value(static_cast< Vs && >(vs)...)))
bool operator>=(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
const Error & error() const &
const Value * get_pointer(const Expected< Value, Error > &ex) noexcept
void swap(exception_wrapper &a, exception_wrapper &b) noexcept
constexpr ExpectedStorage(ErrorTag, Es &&...es) noexcept(noexcept(Error(static_cast< Es && >(es)...)))
bool operator==(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
void assignValue(Vs &&...vs)
bool operator<=(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
auto thenOrThrow(Yes &&yes, No &&no=No{}) const &-> decltype(std::declval< Yes >()(std::declval< const Value & >()))
Expected & operator=(Expected< V, E > that)
typename std::remove_reference< Expected >::type::error_type ExpectedErrorType
constexpr ExpectedStorage(ErrorTag, Es &&...es) noexcept(noexcept(Error(static_cast< Es && >(es)...)))
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
const Error & error() const &
auto then(Fns &&...fns) const &-> decltype(expected_detail::ExpectedHelper::then_(std::declval< const Base & >(), std::declval< Fns >()...))
static constexpr bool uninitializedByException() noexcept
Value value_or(U &&dflt)&&
expected_detail::UnexpectedTag(&)(expected_detail::UnexpectedTag) unexpected_t
Expected(Expected< V, E > that)
T && operator,(T &&t, Unit) noexcept
MoveConstructible(MoveConstructible &&that) noexcept(Noexcept)
constexpr bool isSelfAssign(const void *) const
static constexpr Expected< T, Error > return_(Expected< T, U > t)
FOLLY_PUSH_WARNING FOLLY_MSVC_DISABLE_WARNING(4702) Error &error()&
constexpr ExpectedStorage(EmptyTag) noexcept
const Value & operator*() const &
constexpr Unexpected(Unexpected< Other > that)
std::enable_if< IsLessThanComparable< Value >::value, bool >::type operator<(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
static unordered_set< string > us
FOLLY_NOINLINE FOLLY_COLD void throw_exception(Ex &&ex)
auto thenOrThrow(Yes &&yes, No &&no=No{})&&-> decltype(std::declval< Yes >()(std::declval< Value && >()))
#define FOLLY_REQUIRES_TRAILING(...)