26 template <
class... Args>
27 [[nodiscard]]
constexpr Optional(Args&&... args) : mValue(std::forward<Args>(args)...),
31 Optional& operator=(
Optional&&)
noexcept(std::is_nothrow_move_assignable_v<T>) =
default;
33 Optional& operator=(
Optional const&)
noexcept(std::is_nothrow_copy_assignable_v<T>) =
default;
36 [[nodiscard]]
constexpr Optional(
Optional&&)
noexcept(std::is_nothrow_move_constructible_v<T>) =
default;
38 [[nodiscard]]
constexpr Optional(
Optional const&)
noexcept(std::is_nothrow_copy_constructible_v<T>) =
default;
40 [[nodiscard]]
constexpr explicit operator bool()
const noexcept {
return hasValue; }
42 [[nodiscard]]
constexpr bool has_value()
const noexcept {
return hasValue; }
44 [[nodiscard]]
constexpr T
const* as_ptr()
const noexcept {
return hasValue ? &mValue :
nullptr; }
46 [[nodiscard]]
constexpr T* as_ptr()
noexcept {
return hasValue ? &mValue :
nullptr; }
48 [[nodiscard]]
constexpr T
const& get()
const& {
50 throw std::bad_optional_access{};
55 [[nodiscard]]
constexpr T& get() & {
57 throw std::bad_optional_access{};
62 [[nodiscard]]
constexpr T
const&& get()
const&& {
64 throw std::bad_optional_access{};
66 return std::move(mValue);
69 [[nodiscard]]
constexpr T&& get() && {
71 throw std::bad_optional_access{};
73 return std::move(mValue);
76 [[nodiscard]]
constexpr T
const&& value()
const&& {
return std::move(get()); }
77 [[nodiscard]]
constexpr T&& value() && {
return std::move(get()); }
78 [[nodiscard]]
constexpr T
const& value()
const& {
return get(); }
79 [[nodiscard]]
constexpr T& value() & {
return get(); }
81 [[nodiscard]]
constexpr T
const&& operator*()
const&& {
return std::move(get()); }
82 [[nodiscard]]
constexpr T&& operator*() && {
return std::move(get()); }
83 [[nodiscard]]
constexpr T
const& operator*()
const& {
return get(); }
84 [[nodiscard]]
constexpr T& operator*() & {
return get(); }
86 [[nodiscard]]
constexpr T
const* operator->()
const {
return &get(); }
87 [[nodiscard]]
constexpr T* operator->() {
return &get(); }
89 [[nodiscard]]
constexpr operator T
const&&()
const&& {
return std::move(get()); }
90 [[nodiscard]]
constexpr operator T&&() && {
return std::move(get()); }
91 [[nodiscard]]
constexpr operator T
const&()
const& {
return get(); }
92 [[nodiscard]]
constexpr operator T&() & {
return get(); }
94 [[nodiscard]]
constexpr operator T
const*()
const {
return &get(); }
95 [[nodiscard]]
constexpr operator T*() {
return &get(); }
98 [[nodiscard]]
constexpr T value_or(U&& right)
const& {
102 return static_cast<T const&
>(std::forward<U>(right));
106 [[nodiscard]]
constexpr T&& value_or(U&& right) && {
108 return std::move(mValue);
110 return static_cast<T&&
>(std::forward<U>(right));
114 constexpr auto and_then(Fn&& fn) & {
115 using Ret = std::invoke_result_t<Fn, T&>;
117 return std::invoke(std::forward<Fn>(fn),
static_cast<T&
>(mValue));
119 return std::remove_cvref_t<Ret>{};
124 constexpr auto and_then(Fn&& fn)
const& {
125 using Ret = std::invoke_result_t<Fn, T const&>;
127 return std::invoke(std::forward<Fn>(fn),
static_cast<T const&
>(mValue));
129 return std::remove_cvref_t<Ret>{};
134 constexpr auto and_then(Fn&& fn) && {
135 using Ret = std::invoke_result_t<Fn, T>;
137 return std::invoke(std::forward<Fn>(fn),
static_cast<T&&
>(mValue));
139 return std::remove_cvref_t<Ret>{};
144 constexpr auto and_then(Fn&& fn)
const&& {
145 using Ret = std::invoke_result_t<Fn, T const>;
147 return std::invoke(std::forward<Fn>(fn),
static_cast<T const&&
>(mValue));
149 return std::remove_cvref_t<Ret>{};
154 constexpr auto transform(Fn&& fn) & {
155 using Ret = std::remove_cv_t<std::invoke_result_t<Fn, T&>>;
157 return std::optional<Ret>{
159 meta::elide(std::forward<Fn>(fn),
static_cast<T&
>(mValue))
162 return std::optional<Ret>{};
167 constexpr auto transform(Fn&& fn)
const& {
168 using Ret = std::remove_cv_t<std::invoke_result_t<Fn, T const&>>;
170 return std::optional<Ret>{
meta::elide(std::forward<Fn>(fn),
static_cast<T const&
>(mValue))};
172 return std::optional<Ret>{};
177 constexpr auto transform(Fn&& fn) && {
178 using Ret = std::remove_cv_t<std::invoke_result_t<Fn, T>>;
180 return std::optional<Ret>{
meta::elide(std::forward<Fn>(fn),
static_cast<T&&
>(mValue))};
182 return std::optional<Ret>{};
187 constexpr auto transform(Fn&& fn)
const&& {
188 using Ret = std::remove_cv_t<std::invoke_result_t<Fn, T const>>;
190 return std::optional<Ret>{
meta::elide(std::forward<Fn>(fn),
static_cast<T const&&
>(mValue))};
192 return std::optional<Ret>{};
196 template <std::invocable<> Fn>
197 requires std::copy_constructible<T>
198 constexpr std::optional<T> or_else(Fn&& fn)
const& {
202 return std::invoke(std::forward<Fn>(fn));
206 template <std::invocable<> Fn>
207 requires std::move_constructible<T>
208 constexpr std::optional<T> or_else(Fn&& fn) && {
210 return std::move(*
this);
212 return std::invoke(std::forward<Fn>(fn));
216 [[nodiscard]]
constexpr T
const&& value_or_default()
const&& {
return std::move(value()); }
217 [[nodiscard]]
constexpr T&& value_or_default() && {
return std::move(value()); }
218 [[nodiscard]]
constexpr T
const& value_or_default()
const& {
return value(); }
219 [[nodiscard]]
constexpr T& value_or_default() & {
return value(); }
221 template <
typename U = std::decay_t<T>>
222 requires(std::is_constructible_v<U, T>)
223 [[nodiscard]]
constexpr std::optional<U> copy_as_optional()
const {
224 return has_value() ? std::optional<U>(mValue) : std::nullopt;