1 #ifndef NTA_OPTION_H_INCLUDED
2 #define NTA_OPTION_H_INCLUDED
6 #include "nta/MyEngine.h"
7 #include "nta/format.h"
19 using type =
typename std::remove_reference<T>::type;
21 struct Nop {
Nop(
const type&& _) {} };
23 using storage_type =
typename std::conditional<std::is_reference<T>::value,
25 using placement_type =
typename std::conditional<std::is_reference<T>::value,
30 if constexpr (std::is_reference<T>::value) {
32 new(&m_data)
const void*(std::addressof(d));
34 new(&m_data) placement_type(std::move(d));
38 typename std::aligned_storage_t<
sizeof(storage_type),
alignof(storage_type)> m_data;
46 ~
Option() { m_some =
false; }
52 explicit operator bool()
const {
return m_some; }
64 T
get_or(
const T& optb) {
return m_some ?
get() : optb; }
65 T unwrap_or(
const T& optb) {
return get_or(optb); }
71 Option<S>
map(std::function<S(T)> func);
73 Option<S>
map(std::function<Option<S>(T)> func);
75 S map_or(std::function<S(T)> func,
const S& def);
76 void map(std::function<
void(T)> func);
78 template<
typename T>
template<
typename S>
80 static_assert(std::is_convertible_v<S, T>,
81 "Option: attempted invalid conversion from Option<S> to Option<T>");
83 *
this = orig ? some(orig.unwrap()) : none();
89 assert(
false &&
"Tried getting data from a none Option");
90 }
else if (std::is_reference<T>::value) {
91 return (T)**
reinterpret_cast<const type *
const *
>(&m_data);
93 return (T)*
reinterpret_cast<const type*
>(&m_data);
99 reinterpret_cast<type*
>(&m_data)->~type();
103 template<
typename T>
template<
typename S>
107 template<
typename T>
template<
typename S>
109 return m_some ? func(get()) :
Option<S>::none();
111 template<
typename T>
template<
typename S>
112 S Option<T>::map_or(std::function<S(T)> func,
const S& def) {
113 return m_some ? func(get()) : def;
117 if (m_some) func(get());
119 template<
typename T,
typename S,
typename std::enable_if_t<can_check_equality<T, S>,
void*> =
nullptr>
120 bool operator==(
const Option<T>& lhs,
const S& rhs) {
121 return lhs.is_some() && lhs.unwrap() == rhs;
123 template<
typename T,
typename S,
typename std::enable_if_t<can_check_equality<T, S>,
void*> =
nullptr>
124 bool operator==(
const Option<T>& lhs,
const Option<S>& rhs) {
125 return (lhs.is_none() && rhs.is_none()) ||
126 (lhs && rhs && lhs.unwarp() == rhs.unwarp());
128 template<
typename T,
typename S,
typename std::enable_if_t<can_check_equality<T, S>,
void*> =
nullptr>
129 bool operator==(
const T& lhs,
const Option<S>& rhs) {
130 return rhs.is_some() && lhs == rhs.unwrap();
144 std::string operator()(
const Option<T>& arg) {
145 using decayed =
typename std::decay<T>::type;
160 #endif // NTA_OPTION_H_INCLUDED