14 static_assert(!std::is_reference_v<T>);
17 [[nodiscard]]
constexpr optional_ref()
noexcept =
default;
19 [[nodiscard]]
constexpr optional_ref(std::nullopt_t)
noexcept {}
21 [[nodiscard]]
constexpr optional_ref(std::nullptr_t)
noexcept {}
24 requires(std::is_convertible_v<U*, T*>)
25 [[nodiscard]]
constexpr optional_ref(std::optional<U>& o) noexcept : mPtr(o ? std::addressof(*o) :
nullptr) {}
29 requires(std::is_convertible_v<U*, T*>)
30 [[nodiscard]]
constexpr optional_ref(U* p) noexcept : mPtr(p) {}
34 requires(std::is_convertible_v<U*, T*>)
35 [[nodiscard]]
constexpr optional_ref(U& r) noexcept : mPtr(std::addressof(r)) {}
39 requires(std::is_convertible_v<U*, T*>)
40 [[nodiscard]]
constexpr optional_ref(U
const& r) noexcept : mPtr(std::addressof(r)) {}
44 requires(std::is_convertible_v<U*, T*>)
45 [[nodiscard]]
constexpr optional_ref(
const std::optional<U>& o) noexcept : mPtr(o ? &*o :
nullptr) {}
48 requires(std::is_convertible_v<U*, T*>)
59 [[nodiscard]]
constexpr explicit operator bool()
const noexcept {
return mPtr !=
nullptr; }
61 [[nodiscard]]
constexpr bool has_value()
const noexcept {
return mPtr !=
nullptr; }
63 [[nodiscard]]
constexpr T* as_ptr()
const noexcept {
return mPtr; }
65 [[nodiscard]]
constexpr T& value()
const {
67 throw std::bad_optional_access{};
72 [[nodiscard]]
constexpr T& get()
const {
return value(); }
73 [[nodiscard]]
constexpr T& operator*()
const noexcept {
return *as_ptr(); }
74 [[nodiscard]]
constexpr T* operator->()
const noexcept {
return as_ptr(); }
76 [[nodiscard]]
constexpr operator T&()
const {
return value(); }
77 [[nodiscard]]
constexpr operator T*()
const noexcept {
return as_ptr(); }
80 [[nodiscard]]
constexpr T& value_or(U& right)
const& {
84 return static_cast<T&
>(right);
88 [[nodiscard]]
constexpr T value_or(U&& right)
const&& {
92 return std::forward<U>(right);
95 template <
typename U = std::decay_t<T>>
96 requires(std::is_constructible_v<U, T>)
97 [[nodiscard]]
constexpr std::optional<U> copy_as_optional()
const {
98 return mPtr ? std::optional<U>(*mPtr) : std::nullopt;
101 template <
class... Types>
102 constexpr decltype(
auto)
operator()(Types&&... args)
const
103 noexcept(
noexcept(std::invoke(value(),
static_cast<Types&&
>(args)...))) {
104 return (std::invoke(value(),
static_cast<Types&&
>(args)...));
107 [[nodiscard]]
constexpr decltype(
auto)
operator[](Arg&& index)
const {
108 return (value()[std::forward<Arg>(index)]);
110 [[nodiscard]]
constexpr decltype(
auto) end()
const {
return (value().end()); }
111 [[nodiscard]]
constexpr decltype(
auto) begin()
const {
return (value().begin()); }
112 [[nodiscard]]
constexpr decltype(
auto) cend()
const {
return (value().cend()); }
113 [[nodiscard]]
constexpr decltype(
auto) cbegin()
const {
return (value().cbegin()); }
114 [[nodiscard]]
constexpr decltype(
auto) rend()
const {
return (value().rend()); }
115 [[nodiscard]]
constexpr decltype(
auto) rbegin()
const {
return (value().rbegin()); }
116 [[nodiscard]]
constexpr decltype(
auto) crend()
const {
return (value().crend()); }
117 [[nodiscard]]
constexpr decltype(
auto) crbegin()
const {
return (value().crbegin()); }
120 constexpr auto and_then(Fn&& fn)
const {
121 using Ret = std::invoke_result_t<Fn, T&>;
123 return std::invoke(std::forward<Fn>(fn),
static_cast<T&
>(*mPtr));
125 return std::remove_cvref_t<Ret>{};
129 constexpr auto transform(Fn&& fn)
const {
130 using Ret = std::invoke_result_t<Fn, T&>;
131 if constexpr (std::is_lvalue_reference_v<Ret> || std::is_pointer_v<Ret>) {
132 using UnwrapT = std::remove_pointer_t<std::remove_reference_t<Ret>>;
139 using UnwrapT = std::remove_cv_t<Ret>;
141 return std::optional<UnwrapT>{
ll::meta::elide(std::forward<Fn>(fn),
static_cast<T&
>(*mPtr))};
143 return std::optional<UnwrapT>{};
147 template <std::invocable<> Fn>
148 constexpr auto or_else(Fn&& fn)
const -> std::invoke_result_t<Fn> {
152 return std::invoke(std::forward<Fn>(fn));