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 {}
25 requires(std::is_convertible_v<U*, T*>)
26 constexpr optional_ref(U
const&& r)
noexcept =
delete;
30 requires(std::is_convertible_v<U*, T*>)
31 [[nodiscard]]
constexpr optional_ref(std::optional<U>& o) noexcept : mPtr(o ? std::addressof(*o) :
nullptr) {}
35 requires(std::is_convertible_v<U*, T*>)
36 [[nodiscard]]
constexpr optional_ref(U* p) noexcept : mPtr(p) {}
40 requires(std::is_convertible_v<U*, T*>)
41 [[nodiscard]]
constexpr optional_ref(U& r) noexcept : mPtr(std::addressof(r)) {}
45 requires(std::is_convertible_v<U*, T*>)
46 [[nodiscard]]
constexpr optional_ref(U
const& r) noexcept : mPtr(std::addressof(r)) {}
50 requires(std::is_convertible_v<U*, T*>)
51 [[nodiscard]]
constexpr optional_ref(
const std::optional<U>& o) noexcept : mPtr(o ? &*o :
nullptr) {}
54 requires(std::is_convertible_v<U*, T*>)
55 [[nodiscard]]
constexpr optional_ref(optional_ref<U> rhs) noexcept : mPtr(rhs.as_ptr()) {}
57 [[nodiscard]]
constexpr optional_ref(optional_ref&&)
noexcept =
default;
59 LL_MAY_CONSTEXPR optional_ref& operator=(optional_ref&&)
noexcept =
default;
61 [[nodiscard]]
constexpr optional_ref(optional_ref
const&)
noexcept =
default;
63 LL_MAY_CONSTEXPR optional_ref& operator=(optional_ref
const&)
noexcept =
default;
65 [[nodiscard]]
constexpr explicit operator bool()
const noexcept {
return mPtr !=
nullptr; }
67 [[nodiscard]]
constexpr bool has_value()
const noexcept {
return mPtr !=
nullptr; }
69 [[nodiscard]]
constexpr T* as_ptr()
const noexcept {
return mPtr; }
71 [[nodiscard]]
constexpr T& value()
const {
73 throw std::bad_optional_access{};
78 [[nodiscard]]
constexpr T& get()
const {
return value(); }
79 [[nodiscard]]
constexpr T& operator*()
const noexcept {
return *as_ptr(); }
80 [[nodiscard]]
constexpr T* operator->()
const noexcept {
return as_ptr(); }
82 [[nodiscard]]
constexpr operator T&()
const {
return value(); }
83 [[nodiscard]]
constexpr operator T*()
const noexcept {
return as_ptr(); }
86 [[nodiscard]]
constexpr T& value_or(U& right)
const& {
90 return static_cast<T&
>(right);
94 [[nodiscard]]
constexpr T value_or(U&& right)
const&& {
98 return std::forward<U>(right);
101 template <
typename U = std::decay_t<T>>
102 requires(std::is_constructible_v<U, T>)
103 [[nodiscard]]
constexpr std::optional<U> copy_as_optional()
const {
104 return mPtr ? std::optional<U>(*mPtr) : std::nullopt;
107 template <
class... Types>
108 constexpr decltype(
auto)
109 operator()(Types&&... args)
const noexcept(
noexcept(std::invoke(value(),
static_cast<Types&&
>(args)...))) {
110 return (std::invoke(value(),
static_cast<Types&&
>(args)...));
113 [[nodiscard]]
constexpr decltype(
auto)
operator[](Arg&& index)
const {
114 return (value()[std::forward<Arg>(index)]);
116 [[nodiscard]]
constexpr decltype(
auto) end()
const {
return (value().end()); }
117 [[nodiscard]]
constexpr decltype(
auto) begin()
const {
return (value().begin()); }
118 [[nodiscard]]
constexpr decltype(
auto) cend()
const {
return (value().cend()); }
119 [[nodiscard]]
constexpr decltype(
auto) cbegin()
const {
return (value().cbegin()); }
120 [[nodiscard]]
constexpr decltype(
auto) rend()
const {
return (value().rend()); }
121 [[nodiscard]]
constexpr decltype(
auto) rbegin()
const {
return (value().rbegin()); }
122 [[nodiscard]]
constexpr decltype(
auto) crend()
const {
return (value().crend()); }
123 [[nodiscard]]
constexpr decltype(
auto) crbegin()
const {
return (value().crbegin()); }
126 constexpr auto and_then(Fn&& fn)
const {
127 using Ret = std::invoke_result_t<Fn, T&>;
129 return std::invoke(std::forward<Fn>(fn),
static_cast<T&
>(*mPtr));
131 return std::remove_cvref_t<Ret>{};
135 constexpr auto transform(Fn&& fn)
const {
136 using Ret = std::invoke_result_t<Fn, T&>;
137 if constexpr (std::is_lvalue_reference_v<Ret> || std::is_pointer_v<Ret>) {
138 using UnwrapT = std::remove_pointer_t<std::remove_reference_t<Ret>>;
140 return optional_ref<UnwrapT>{std::invoke(std::forward<Fn>(fn),
static_cast<T&
>(*mPtr))};
142 return optional_ref<UnwrapT>{};
145 using UnwrapT = std::remove_cv_t<Ret>;
147 return std::optional<UnwrapT>{
ll::meta::elide(std::forward<Fn>(fn),
static_cast<T&
>(*mPtr))};
149 return std::optional<UnwrapT>{};
153 template <std::invocable<> Fn>
154 constexpr auto or_else(Fn&& fn)
const -> std::invoke_result_t<Fn> {
158 return std::invoke(std::forward<Fn>(fn));