13 #include <type_traits>
17 class bad_nullable_access :
public std::runtime_error
21 : std::runtime_error(
"nullable object doesn't have a value") { }
27 template <
typename T,
typename = std::enable_if_t<!std::is_po
inter_v<T>>>
32 : m_value{ }, m_hasValue(
false) { }
35 : m_value(std::move(value)), m_hasValue(
true) { }
38 : m_value{ }, m_hasValue(
false) { }
47 m_value = std::move(value);
58 const T& value()
const
61 throw bad_nullable_access();
69 throw bad_nullable_access();
74 bool has_value()
const {
return m_hasValue; }
75 const T* operator->()
const {
return &m_value; }
76 T* operator->() {
return &m_value; }
77 const T& operator*()
const {
return m_value; }
78 T& operator*() {
return m_value; }
81 template <
typename T2>
84 template <
typename T2>
87 template <
typename T2>
90 template <
typename T2>
93 template <
typename T2>
96 template <
typename T2>
99 template <
typename T2>
100 friend bool operator==(
const nullable<T2>& lhs,
const T2& rhs);
102 template <
typename T2>
103 friend bool operator==(
const T2& lhs,
const nullable<T2>& rhs);
105 template <
typename T2>
106 friend bool operator==(
const nullable<T2>& lhs, std::nullptr_t);
108 template <
typename T2>
109 friend bool operator!=(
const nullable<T2>& lhs,
const T2& rhs);
111 template <
typename T2>
112 friend bool operator!=(
const T2& lhs,
const nullable<T2>& rhs);
114 template <
typename T2>
115 friend bool operator==(std::nullptr_t,
const nullable<T2>& rhs);
117 template <
typename T2>
118 friend bool operator!=(
const nullable<T2>& lhs, std::nullptr_t);
120 template <
typename T2>
121 friend bool operator!=(std::nullptr_t,
const nullable<T2>& rhs);
129 template <
typename T>
134 : m_value{ }, m_hasValue(false){ }
137 : m_value(&value), m_hasValue(true) { }
139 nullable(std::nullptr_t)
140 : m_value{ }, m_hasValue(false) { }
143 template <
typename T2, std::enable_if_t<std::is_convertible_v<std::add_po
inter_t<std::remove_reference_t<T2>>,
144 std::add_po
inter_t<std::remove_reference_t<T>>>,
int> = 0>
145 nullable(
const nullable<T2&>& value)
146 : m_value(reinterpret_cast<const nullable&>(value).m_value), m_hasValue(reinterpret_cast<const nullable&>(value).m_hasValue) { }
148 nullable(
const nullable& value) =
default;
150 nullable& operator=(
const nullable& value) =
default;
152 const T& value()
const
155 throw bad_nullable_access();
163 throw bad_nullable_access();
168 bool has_value()
const {
return m_hasValue; }
169 const T* operator->()
const {
return m_value; }
170 T* operator->() {
return m_value; }
171 const T& operator*()
const {
return *m_value; }
172 T& operator*() {
return *m_value; }
175 template <
typename T2>
176 friend bool operator==(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs);
178 template <
typename T2>
179 friend bool operator!=(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs);
181 template <
typename T2>
182 friend bool operator==(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs);
184 template <
typename T2>
185 friend bool operator!=(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs);
187 template <
typename T2>
188 friend bool operator==(
const nullable<T2&>& lhs,
const nullable<T2&>& rhs);
190 template <
typename T2>
191 friend bool operator!=(
const nullable<T2&>& lhs,
const nullable<T2&>& rhs);
193 template <
typename T2>
194 friend bool operator==(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs);
196 template <
typename T2>
197 friend bool operator!=(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs);
199 template <
typename T2>
200 friend bool operator==(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs);
202 template <
typename T2>
203 friend bool operator!=(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs);
205 template <
typename T2>
206 friend bool operator==(
const nullable<T2>& lhs, std::nullptr_t);
208 template <
typename T2>
209 friend bool operator==(std::nullptr_t,
const nullable<T2>& rhs);
211 template <
typename T2>
212 friend bool operator!=(
const nullable<T2>& lhs, std::nullptr_t);
214 template <
typename T2>
215 friend bool operator!=(std::nullptr_t,
const nullable<T2>& rhs);
222 template <
typename T2>
223 bool operator==(
const nullable<T2>& lhs,
const nullable<T2>& rhs)
225 if (lhs.m_hasValue != rhs.m_hasValue)
229 return lhs.m_value == rhs.m_value;
234 template <
typename T2>
235 bool operator!=(
const nullable<T2>& lhs,
const nullable<T2>& rhs)
237 if (lhs.m_hasValue != rhs.m_hasValue)
241 return lhs.m_value != rhs.m_value;
246 template <
typename T2>
247 bool operator==(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs)
249 if (lhs.m_hasValue != rhs.m_hasValue)
253 return lhs.m_value == *rhs.m_value;
258 template <
typename T2>
259 bool operator!=(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs)
261 if (lhs.m_hasValue != rhs.m_hasValue)
265 return lhs.m_value != *rhs.m_value;
270 template <
typename T2>
271 bool operator==(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs)
273 if (lhs.m_hasValue != rhs.m_hasValue)
277 return *lhs.m_value == rhs.m_value;
282 template <
typename T2>
283 bool operator!=(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs)
285 if (lhs.m_hasValue != rhs.m_hasValue)
289 return *lhs.m_value != rhs.m_value;
294 template <
typename T2>
295 bool operator==(
const nullable<T2&>& lhs,
const nullable<T2&>& rhs)
297 if (lhs.m_hasValue != rhs.m_hasValue)
301 return *lhs.m_value == *rhs.m_value;
306 template <
typename T2>
307 bool operator!=(
const nullable<T2&>& lhs,
const nullable<T2&>& rhs)
309 if (lhs.m_hasValue != rhs.m_hasValue)
313 return *lhs.m_value != *rhs.m_value;
318 template <
typename T2>
319 bool operator==(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs)
324 return *lhs.m_value == rhs;
327 template <
typename T2>
328 bool operator!=(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs)
333 return *lhs.m_value != rhs;
336 template <
typename T2>
337 bool operator==(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs)
342 return lhs == *rhs.m_value;
345 template <
typename T2>
346 bool operator!=(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs)
351 return lhs != *rhs.m_value;
354 template <
typename T2>
355 bool operator==(
const nullable<T2>& lhs,
const T2& rhs)
360 return lhs.m_value == rhs;
363 template <
typename T2>
364 bool operator!=(
const nullable<T2>& lhs,
const T2& rhs)
369 return lhs.m_value != rhs;
372 template <
typename T2>
373 bool operator==(
const T2& lhs,
const nullable<T2>& rhs)
378 return lhs == rhs.m_value;
381 template <
typename T2>
382 bool operator!=(
const T2& lhs,
const nullable<T2>& rhs)
387 return lhs != rhs.m_value;
390 template <
typename T2>
391 bool operator==(
const nullable<T2>& lhs, std::nullptr_t)
393 return !lhs.m_hasValue;
396 template <
typename T2>
397 bool operator!=(
const nullable<T2>& lhs, std::nullptr_t)
399 return lhs.m_hasValue;
402 template <
typename T2>
403 bool operator==(std::nullptr_t,
const nullable<T2>& rhs)
405 return !rhs.m_hasValue;
408 template <
typename T2>
409 bool operator!=(std::nullptr_t,
const nullable<T2>& rhs)
411 return rhs.m_hasValue;
Alternative to std::optional that supports reference (but not pointer) types.
Definition: nullable.h:29
SPDX-FileCopyrightText: (C) 2022 Francesco Pretto ceztko@gmail.com SPDX-License-Identifier: LGPL-2....
Definition: basetypes.h:16