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_dummy{ }, m_hasValue(
false) { }
35 : m_value(std::move(value)), m_hasValue(
true) { }
38 : m_dummy{ }, m_hasValue(
false) { }
45 new(&m_value)T(value.m_value);
66 m_value = value.m_value;
78 new(&m_value)T(value.m_value);
90 m_value = std::move(value);
94 new(&m_value)T(std::move(value));
118 const T& value()
const
121 throw bad_nullable_access();
126 bool has_value()
const {
return m_hasValue; }
127 const T* operator->()
const {
return &m_value; }
128 const T& operator*()
const {
return m_value; }
129 operator const T* ()
const
138 template <
typename T2>
141 template <
typename T2>
144 template <
typename T2>
147 template <
typename T2>
150 template <
typename T2>
153 template <
typename T2>
156 template <
typename T2>
159 template <
typename T2>
162 template <
typename T2>
165 template <
typename T2>
168 template <
typename T2>
169 friend std::enable_if_t<!std::is_reference_v<T2>,
bool> operator==(
const nullable<T2>&
lhs, std::nullptr_t);
171 template <
typename T2>
172 friend std::enable_if_t<!std::is_reference_v<T2>,
bool> operator==(std::nullptr_t,
const nullable<T2>&
rhs);
174 template <
typename T2>
175 friend std::enable_if_t<!std::is_reference_v<T2>,
bool> operator!=(
const nullable<T2>&
lhs, std::nullptr_t);
177 template <
typename T2>
178 friend std::enable_if_t<!std::is_reference_v<T2>,
bool> operator!=(std::nullptr_t,
const nullable<T2>&
rhs);
181 struct NonTrivialDummyType
183 constexpr NonTrivialDummyType()
noexcept
192 NonTrivialDummyType m_dummy;
199 template <
typename TRef>
202 using T = std::remove_reference_t<TRef>;
208 : m_value(&value) { }
213 nullable(std::nullptr_t)
217 template <
typename T2,
typename = std::enable_if_t<
218 std::is_convertible_v<std::add_pointer_t<std::remove_reference_t<T2>>,
219 std::add_pointer_t<std::remove_reference_t<T>>>,
int>>
220 nullable(
const nullable<T2&>& value)
221 : m_value(reinterpret_cast<const nullable&>(value).m_value) { }
223 nullable(
const nullable& value) =
default;
225 nullable& operator=(
const nullable& value) =
default;
229 if (m_value ==
nullptr)
230 throw bad_nullable_access();
235 bool has_value()
const {
return m_value !=
nullptr; }
237 explicit operator T* ()
const {
return m_value; }
238 T* operator->()
const {
return m_value; }
239 T& operator*()
const {
return *m_value; }
242 template <
typename T2>
243 friend bool operator==(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs);
245 template <
typename T2>
246 friend bool operator==(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs);
248 template <
typename T2>
249 friend bool operator!=(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs);
251 template <
typename T2>
252 friend bool operator!=(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs);
254 template <
typename T2>
255 friend bool operator==(
const nullable<T2&>& lhs,
const nullable<T2&>& rhs);
257 template <
typename T2>
258 friend bool operator==(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs);
260 template <
typename T2>
261 friend bool operator==(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs);
263 template <
typename T2>
264 friend bool operator!=(
const nullable<T2&>& lhs,
const nullable<T2&>& rhs);
266 template <
typename T2>
267 friend bool operator!=(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs);
269 template <
typename T2>
270 friend bool operator!=(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs);
272 template <
typename T2>
273 friend std::enable_if_t<std::is_reference_v<T2>,
bool> operator==(
const nullable<T2>& lhs, std::nullptr_t);
275 template <
typename T2>
276 friend std::enable_if_t<std::is_reference_v<T2>,
bool> operator==(std::nullptr_t,
const nullable<T2>& rhs);
278 template <
typename T2>
279 friend std::enable_if_t<std::is_reference_v<T2>,
bool> operator!=(
const nullable<T2>& lhs, std::nullptr_t);
281 template <
typename T2>
282 friend std::enable_if_t<std::is_reference_v<T2>,
bool> operator!=(std::nullptr_t,
const nullable<T2>& rhs);
284 template <
typename T2>
285 friend bool operator==(
const nullable<T2&>& lhs,
const T2* rhs);
287 template <
typename T2>
288 friend bool operator==(
const T2* lhs,
const nullable<T2&>& rhs);
290 template <
typename T2>
291 friend bool operator!=(
const nullable<T2&>& lhs,
const T2* rhs);
293 template <
typename T2>
294 friend bool operator!=(
const T2* lhs,
const nullable<T2&>& rhs);
300 template <
typename T2>
301 bool operator==(
const nullable<T2>& lhs,
const nullable<T2>& rhs)
303 if (lhs.m_hasValue != rhs.m_hasValue)
307 return lhs.m_value == rhs.m_value;
312 template <
typename T2>
313 bool operator!=(
const nullable<T2>& lhs,
const nullable<T2>& rhs)
315 if (lhs.m_hasValue != rhs.m_hasValue)
319 return lhs.m_value != rhs.m_value;
324 template <
typename T2>
325 bool operator==(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs)
327 if (lhs.m_hasValue != rhs.has_value())
331 return lhs.m_value == *rhs.m_value;
336 template <
typename T2>
337 bool operator!=(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs)
339 if (lhs.m_hasValue != rhs.has_value())
343 return lhs.m_value != *rhs.m_value;
348 template <
typename T2>
349 bool operator==(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs)
351 if (lhs.has_value() != rhs.m_hasValue)
355 return *lhs.m_value == rhs.m_value;
360 template <
typename T2>
361 bool operator!=(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs)
363 if (lhs.has_value() != rhs.m_hasValue)
367 return *lhs.m_value != rhs.m_value;
372 template <
typename T2>
373 bool operator==(
const nullable<T2&>& lhs,
const nullable<T2&>& rhs)
375 if (lhs.has_value() != rhs.has_value())
379 return *lhs.m_value == *rhs.m_value;
384 template <
typename T2>
385 bool operator!=(
const nullable<T2&>& lhs,
const nullable<T2&>& rhs)
387 if (lhs.has_value() != rhs.has_value())
391 return *lhs.m_value != *rhs.m_value;
396 template <
typename T2>
397 bool operator==(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs)
399 if (!lhs.has_value())
402 return *lhs.m_value == rhs;
405 template <
typename T2>
406 bool operator!=(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs)
408 if (!lhs.has_value())
411 return *lhs.m_value != rhs;
414 template <
typename T2>
415 bool operator==(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs)
417 if (!rhs.has_value())
420 return lhs == *rhs.m_value;
423 template <
typename T2>
424 bool operator!=(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs)
426 if (!rhs.has_value())
429 return lhs != *rhs.m_value;
432 template <
typename T2>
433 bool operator==(
const nullable<T2>& lhs,
const T2& rhs)
438 return lhs.m_value == rhs;
441 template <
typename T2>
442 bool operator!=(
const nullable<T2>& lhs,
const T2& rhs)
447 return lhs.m_value != rhs;
450 template <
typename T2>
451 bool operator==(
const T2& lhs,
const nullable<T2>& rhs)
456 return lhs == rhs.m_value;
459 template <
typename T2>
460 bool operator!=(
const T2& lhs,
const nullable<T2>& rhs)
465 return lhs != rhs.m_value;
468 template <
typename T2>
469 std::enable_if_t<!std::is_reference_v<T2>,
bool> operator==(
const nullable<T2>& lhs, std::nullptr_t)
471 return !lhs.m_hasValue;
474 template <
typename T2>
475 std::enable_if_t<!std::is_reference_v<T2>,
bool> operator!=(
const nullable<T2>& lhs, std::nullptr_t)
477 return lhs.m_hasValue;
480 template <
typename T2>
481 std::enable_if_t<!std::is_reference_v<T2>,
bool> operator==(std::nullptr_t,
const nullable<T2>& rhs)
483 return !rhs.m_hasValue;
486 template <
typename T2>
487 std::enable_if_t<!std::is_reference_v<T2>,
bool> operator!=(std::nullptr_t,
const nullable<T2>& rhs)
489 return rhs.m_hasValue;
492 template <
typename T2>
493 std::enable_if_t<std::is_reference_v<T2>,
bool> operator==(
const nullable<T2>& lhs, std::nullptr_t)
495 return lhs.m_value ==
nullptr;
498 template <
typename T2>
499 std::enable_if_t<std::is_reference_v<T2>,
bool> operator==(std::nullptr_t,
const nullable<T2>& rhs)
501 return rhs.m_value ==
nullptr;
504 template <
typename T2>
505 std::enable_if_t<std::is_reference_v<T2>,
bool> operator!=(
const nullable<T2>& lhs, std::nullptr_t)
507 return lhs.m_value !=
nullptr;
510 template <
typename T2>
511 std::enable_if_t<std::is_reference_v<T2>,
bool> operator!=(std::nullptr_t,
const nullable<T2>& rhs)
513 return rhs.m_value !=
nullptr;
516 template<
typename T2>
517 bool operator==(
const nullable<T2&>& lhs,
const T2* rhs)
519 return lhs.m_value == rhs;
522 template<
typename T2>
523 bool operator==(
const T2* lhs,
const nullable<T2&>& rhs)
525 return lhs == rhs.m_value;
528 template<
typename T2>
529 bool operator!=(
const nullable<T2&>& lhs,
const T2* rhs)
531 return lhs.m_value != rhs;
534 template<
typename T2>
535 bool operator!=(
const T2* lhs,
const nullable<T2&>& rhs)
537 return lhs != rhs.m_value;
Convenient type for char array storage and/or buffer with std::string compatibility.
Definition basetypes.h:38
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