#pragma once
#include <cassert>
#include <cstddef>
#include <functional>
#include <new>
#include <optional>
#include <stdexcept>
#include <type_traits>
#include <utility>
#include <folly/Portability.h>
#include <folly/Traits.h>
#include <folly/Utility.h>
#include <folly/lang/Exception.h>
namespace folly {
template <class Value>
class Optional;
namespace detail {
struct OptionalEmptyTag { … };
template <class Value>
struct OptionalPromise;
template <class Value>
struct OptionalPromiseReturn;
}
struct None { … };
constexpr None none{ … };
class FOLLY_EXPORT OptionalEmptyException : public std::runtime_error { … };
template <class Value>
class Optional { … };
template <class T>
const T* get_pointer(const Optional<T>& opt) { … }
template <class T>
T* get_pointer(Optional<T>& opt) { … }
template <class T>
void swap(Optional<T>& a, Optional<T>& b) noexcept(noexcept(a.swap(b))) { … }
template <class T>
constexpr Optional<std::decay_t<T>> make_optional(T&& v) { … }
template <class T, class... Args>
constexpr folly::Optional<T> make_optional(Args&&... args) { … }
template <class T, class U, class... Args>
constexpr folly::Optional<T> make_optional(
std::initializer_list<U> il, Args&&... args) { … }
template <class U, class V>
constexpr bool operator==(const Optional<U>& a, const V& b) { … }
template <class U, class V>
constexpr bool operator!=(const Optional<U>& a, const V& b) { … }
template <class U, class V>
constexpr bool operator==(const U& a, const Optional<V>& b) { … }
template <class U, class V>
constexpr bool operator!=(const U& a, const Optional<V>& b) { … }
template <class U, class V>
constexpr bool operator==(const Optional<U>& a, const Optional<V>& b) { … }
template <class U, class V>
constexpr bool operator!=(const Optional<U>& a, const Optional<V>& b) { … }
template <class U, class V>
constexpr bool operator<(const Optional<U>& a, const Optional<V>& b) { … }
template <class U, class V>
constexpr bool operator>(const Optional<U>& a, const Optional<V>& b) { … }
template <class U, class V>
constexpr bool operator<=(const Optional<U>& a, const Optional<V>& b) { … }
template <class U, class V>
constexpr bool operator>=(const Optional<U>& a, const Optional<V>& b) { … }
template <class V>
bool operator<(const Optional<V>&, const V& other) = delete;
template <class V>
bool operator<=(const Optional<V>&, const V& other) = delete;
template <class V>
bool operator>=(const Optional<V>&, const V& other) = delete;
template <class V>
bool operator>(const Optional<V>&, const V& other) = delete;
template <class V>
bool operator<(const V& other, const Optional<V>&) = delete;
template <class V>
bool operator<=(const V& other, const Optional<V>&) = delete;
template <class V>
bool operator>=(const V& other, const Optional<V>&) = delete;
template <class V>
bool operator>(const V& other, const Optional<V>&) = delete;
template <class V>
constexpr bool operator==(const Optional<V>& a, None) noexcept { … }
template <class V>
constexpr bool operator==(None, const Optional<V>& a) noexcept { … }
template <class V>
constexpr bool operator<(const Optional<V>&, None) noexcept { … }
template <class V>
constexpr bool operator<(None, const Optional<V>& a) noexcept { … }
template <class V>
constexpr bool operator>(const Optional<V>& a, None) noexcept { … }
template <class V>
constexpr bool operator>(None, const Optional<V>&) noexcept { … }
template <class V>
constexpr bool operator<=(None, const Optional<V>&) noexcept { … }
template <class V>
constexpr bool operator<=(const Optional<V>& a, None) noexcept { … }
template <class V>
constexpr bool operator>=(const Optional<V>&, None) noexcept { … }
template <class V>
constexpr bool operator>=(None, const Optional<V>& a) noexcept { … }
}
FOLLY_NAMESPACE_STD_BEGIN
hash<folly::enable_std_hash_helper<folly::Optional<T>, remove_const_t<T>>>;
FOLLY_NAMESPACE_STD_END
#if FOLLY_HAS_COROUTINES
#include <folly/experimental/coro/Coroutine.h>
namespace folly {
namespace detail {
template <typename Value>
struct OptionalPromise;
template <typename Value>
struct OptionalPromiseReturn {
Optional<Value> storage_;
Optional<Value>*& pointer_;
OptionalPromiseReturn(OptionalPromise<Value>& p) noexcept
: pointer_{p.value_} {
pointer_ = &storage_;
}
OptionalPromiseReturn(OptionalPromiseReturn const&) = delete;
~OptionalPromiseReturn() {}
operator Optional<Value>() {
if (folly::coro::detect_promise_return_object_eager_conversion()) {
assert(!storage_.has_value());
return Optional{OptionalEmptyTag{}, pointer_};
} else {
return std::move(storage_);
}
}
};
template <typename Value>
struct OptionalPromise {
Optional<Value>* value_ = nullptr;
OptionalPromise() = default;
OptionalPromise(OptionalPromise const&) = delete;
OptionalPromiseReturn<Value> get_return_object() noexcept { return *this; }
coro::suspend_never initial_suspend() const noexcept { return {}; }
coro::suspend_never final_suspend() const noexcept { return {}; }
template <typename U = Value>
void return_value(U&& u) {
*value_ = static_cast<U&&>(u);
}
void unhandled_exception() {
rethrow_current_exception();
}
};
template <typename Value>
struct OptionalAwaitable {
Optional<Value> o_;
bool await_ready() const noexcept { return o_.hasValue(); }
Value await_resume() { return std::move(o_.value()); }
template <typename U>
void await_suspend(coro::coroutine_handle<OptionalPromise<U>> h) const {
h.destroy();
}
};
}
template <typename Value>
detail::OptionalAwaitable<Value>
operator co_await(Optional<Value> o) {
return {std::move(o)};
}
}
#endif