11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
18PROMEKI_NAMESPACE_BEGIN
49template <
typename T>
class Optional {
55 using DataType = std::optional<T>;
61 Optional(std::nullopt_t)
noexcept {}
67 Optional(
const T &value) : d(value) {}
73 Optional(T &&value)
noexcept(std::is_nothrow_move_constructible_v<T>) : d(std::move(value)) {}
79 Optional(
const DataType &other) : d(other) {}
85 Optional(DataType &&other)
noexcept(std::is_nothrow_move_constructible_v<T>) : d(std::move(other)) {}
88 Optional(
const Optional &other) =
default;
91 Optional(Optional &&other)
noexcept(std::is_nothrow_move_constructible_v<T>) =
default;
94 ~Optional() =
default;
97 Optional &operator=(
const Optional &other) =
default;
100 Optional &operator=(Optional &&other)
noexcept(std::is_nothrow_move_assignable_v<T>) =
default;
103 Optional &operator=(std::nullopt_t)
noexcept {
118 template <
typename U,
119 typename = std::enable_if_t<!std::is_same_v<std::decay_t<U>, Optional> &&
120 !std::is_same_v<std::decay_t<U>, std::nullopt_t> &&
121 std::is_constructible_v<T, U &&>>>
122 Optional &operator=(U &&value) {
123 d = std::forward<U>(value);
131 bool hasValue() const noexcept {
return d.has_value(); }
134 explicit operator bool() const noexcept {
return d.has_value(); }
143 const T &value() const & {
return d.value(); }
151 T &value() & {
return d.value(); }
159 T &&value() && {
return std::move(d).value(); }
166 template <
typename U> T valueOr(U &&fallback)
const & {
167 return d.value_or(std::forward<U>(fallback));
174 template <
typename U> T valueOr(U &&fallback) && {
175 return std::move(d).value_or(std::forward<U>(fallback));
183 const T &operator*() const & noexcept {
return *d; }
189 T &operator*() &
noexcept {
return *d; }
195 T &&operator*() &&
noexcept {
return std::move(*d); }
202 const T *operator->() const noexcept {
return d.operator->(); }
205 T *operator->() noexcept {
return d.operator->(); }
208 void reset() noexcept { d.reset(); }
216 template <
typename... ArgsT> T &emplace(ArgsT &&...args) {
217 return d.emplace(std::forward<ArgsT>(args)...);
221 void swap(Optional &other)
noexcept(std::is_nothrow_swappable_v<T> &&
222 std::is_nothrow_move_constructible_v<T>) {
227 const DataType &toStdOptional() const noexcept {
return d; }
230 DataType &toStdOptional() noexcept {
return d; }
233 friend bool operator==(
const Optional &lhs,
const Optional &rhs) {
return lhs.d == rhs.d; }
236 friend bool operator!=(
const Optional &lhs,
const Optional &rhs) {
return lhs.d != rhs.d; }
239 friend bool operator==(
const Optional &lhs, std::nullopt_t)
noexcept {
return !lhs.d.has_value(); }
242 friend bool operator==(std::nullopt_t,
const Optional &rhs)
noexcept {
return !rhs.d.has_value(); }
245 friend bool operator!=(
const Optional &lhs, std::nullopt_t)
noexcept {
return lhs.d.has_value(); }
248 friend bool operator!=(std::nullopt_t,
const Optional &rhs)
noexcept {
return rhs.d.has_value(); }