14 class bad_nullable_access :
public std::runtime_error
18 : std::runtime_error(
"nullable object doesn't have a value") { }
22 template <
typename T,
typename = std::enable_if_t<!std::is_po
inter_v<T>>>
27 : m_dummy{ }, m_hasValue(
false) { }
30 : m_value(std::move(value)), m_hasValue(
true) { }
33 : m_dummy{ }, m_hasValue(
false) { }
40 new(&m_value)T(value.m_value);
61 m_value = value.m_value;
73 new(&m_value)T(value.m_value);
85 m_value = std::move(value);
89 new(&m_value)T(std::move(value));
102 m_value = std::move(value);
106 new(&m_value)T(std::move(value));
122 operator nullable<const T&>()
const
125 return nullable<const T&>(m_value);
130 const T& value()
const
133 throw bad_nullable_access();
138 bool has_value()
const {
return m_hasValue; }
139 const T* operator->()
const {
return &m_value; }
140 const T& operator*()
const {
return m_value; }
141 operator const T* ()
const
150 template <
typename T2>
151 friend bool operator==(
const nullable<T2>& lhs,
const nullable<T2>& rhs);
153 template <
typename T2>
154 friend bool operator!=(
const nullable<T2>& lhs,
const nullable<T2>& rhs);
156 template <
typename T2>
157 friend bool operator==(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs);
159 template <
typename T2>
160 friend bool operator!=(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs);
162 template <
typename T2>
163 friend bool operator==(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs);
165 template <
typename T2>
166 friend bool operator!=(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs);
168 template <
typename T2>
169 friend bool operator==(
const nullable<T2>& lhs,
const T2& rhs);
171 template <
typename T2>
172 friend bool operator==(
const T2& lhs,
const nullable<T2>& rhs);
174 template <
typename T2>
175 friend bool operator!=(
const nullable<T2>& lhs,
const T2& rhs);
177 template <
typename T2>
178 friend bool operator!=(
const T2& lhs,
const nullable<T2>& rhs);
180 template <
typename T2>
181 friend std::enable_if_t<!std::is_reference_v<T2>,
bool> operator==(
const nullable<T2>& lhs, std::nullptr_t);
183 template <
typename T2>
184 friend std::enable_if_t<!std::is_reference_v<T2>,
bool> operator==(std::nullptr_t,
const nullable<T2>& rhs);
186 template <
typename T2>
187 friend std::enable_if_t<!std::is_reference_v<T2>,
bool> operator!=(
const nullable<T2>& lhs, std::nullptr_t);
189 template <
typename T2>
190 friend std::enable_if_t<!std::is_reference_v<T2>,
bool> operator!=(std::nullptr_t,
const nullable<T2>& rhs);
193 struct NonTrivialDummyType
195 constexpr NonTrivialDummyType() noexcept
204 NonTrivialDummyType m_dummy;
211 template <
typename TRef>
212 class nullable<TRef, std::enable_if_t<std::is_reference_v<TRef>>> final
214 using T = std::remove_reference_t<TRef>;
220 : m_value(&value) { }
225 nullable(std::nullptr_t)
229 template <
typename T2,
typename = std::enable_if_t<
230 std::is_convertible_v<std::add_pointer_t<std::remove_reference_t<T2>>,
231 std::add_pointer_t<std::remove_reference_t<T>>>,
int>>
232 nullable(
const nullable<T2&>& value)
233 : m_value(reinterpret_cast<const nullable&>(value).m_value) { }
235 nullable(
const nullable& value) =
default;
237 nullable& operator=(
const nullable& value) =
default;
241 if (m_value ==
nullptr)
242 throw bad_nullable_access();
247 bool has_value()
const {
return m_value !=
nullptr; }
249 explicit operator T* ()
const {
return m_value; }
250 T* operator->()
const {
return m_value; }
251 T& operator*()
const {
return *m_value; }
254 template <
typename T2>
255 friend bool operator==(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs);
257 template <
typename T2>
258 friend bool operator==(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs);
260 template <
typename T2>
261 friend bool operator!=(
const nullable<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs);
263 template <
typename T2>
264 friend bool operator!=(
const nullable<T2&>& lhs,
const nullable<std::decay_t<T2>>& rhs);
266 template <
typename T2>
267 friend bool operator==(
const nullable<T2&>& lhs,
const nullable<T2&>& rhs);
269 template <
typename T2>
270 friend bool operator==(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs);
272 template <
typename T2>
273 friend bool operator==(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs);
275 template <
typename T2>
276 friend bool operator!=(
const nullable<T2&>& lhs,
const nullable<T2&>& rhs);
278 template <
typename T2>
279 friend bool operator!=(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs);
281 template <
typename T2>
282 friend bool operator!=(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs);
284 template <
typename T2>
285 friend std::enable_if_t<std::is_reference_v<T2>,
bool> operator==(
const nullable<T2>& lhs, std::nullptr_t);
287 template <
typename T2>
288 friend std::enable_if_t<std::is_reference_v<T2>,
bool> operator==(std::nullptr_t,
const nullable<T2>& rhs);
290 template <
typename T2>
291 friend std::enable_if_t<std::is_reference_v<T2>,
bool> operator!=(
const nullable<T2>& lhs, std::nullptr_t);
293 template <
typename T2>
294 friend std::enable_if_t<std::is_reference_v<T2>,
bool> operator!=(std::nullptr_t,
const nullable<T2>& rhs);
296 template <
typename T2>
297 friend bool operator==(
const nullable<T2&>& lhs,
const T2* rhs);
299 template <
typename T2>
300 friend bool operator==(
const T2* lhs,
const nullable<T2&>& rhs);
302 template <
typename T2>
303 friend bool operator!=(
const nullable<T2&>& lhs,
const T2* rhs);
305 template <
typename T2>
306 friend bool operator!=(
const T2* lhs,
const nullable<T2&>& rhs);
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<T2>& lhs,
const nullable<T2>& rhs)
327 if (lhs.m_hasValue != rhs.m_hasValue)
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<std::decay_t<T2>>& lhs,
const nullable<T2&>& rhs)
351 if (lhs.m_hasValue != rhs.has_value())
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<std::decay_t<T2>>& rhs)
375 if (lhs.has_value() != rhs.m_hasValue)
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 nullable<T2&>& rhs)
399 if (lhs.has_value() != rhs.has_value())
403 return *lhs.m_value != *rhs.m_value;
408 template <
typename T2>
409 bool operator==(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs)
411 if (!lhs.has_value())
414 return *lhs.m_value == rhs;
417 template <
typename T2>
418 bool operator!=(
const nullable<T2&>& lhs,
const std::decay_t<T2>& rhs)
420 if (!lhs.has_value())
423 return *lhs.m_value != rhs;
426 template <
typename T2>
427 bool operator==(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs)
429 if (!rhs.has_value())
432 return lhs == *rhs.m_value;
435 template <
typename T2>
436 bool operator!=(
const std::decay_t<T2>& lhs,
const nullable<T2&>& rhs)
438 if (!rhs.has_value())
441 return lhs != *rhs.m_value;
444 template <
typename T2>
445 bool operator==(
const nullable<T2>& lhs,
const T2& rhs)
450 return lhs.m_value == rhs;
453 template <
typename T2>
454 bool operator!=(
const nullable<T2>& lhs,
const T2& rhs)
459 return lhs.m_value != rhs;
462 template <
typename T2>
463 bool operator==(
const T2& lhs,
const nullable<T2>& rhs)
468 return lhs == rhs.m_value;
471 template <
typename T2>
472 bool operator!=(
const T2& lhs,
const nullable<T2>& rhs)
477 return lhs != rhs.m_value;
480 template <
typename T2>
481 std::enable_if_t<!std::is_reference_v<T2>,
bool> operator==(
const nullable<T2>& lhs, std::nullptr_t)
483 return !lhs.m_hasValue;
486 template <
typename T2>
487 std::enable_if_t<!std::is_reference_v<T2>,
bool> operator!=(
const nullable<T2>& lhs, std::nullptr_t)
489 return lhs.m_hasValue;
492 template <
typename T2>
493 std::enable_if_t<!std::is_reference_v<T2>,
bool> operator==(std::nullptr_t,
const nullable<T2>& rhs)
495 return !rhs.m_hasValue;
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_hasValue;
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 std::enable_if_t<std::is_reference_v<T2>,
bool> operator!=(
const nullable<T2>& lhs, std::nullptr_t)
519 return lhs.m_value !=
nullptr;
522 template <
typename T2>
523 std::enable_if_t<std::is_reference_v<T2>,
bool> operator!=(std::nullptr_t,
const nullable<T2>& rhs)
525 return rhs.m_value !=
nullptr;
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;
540 template<
typename T2>
541 bool operator!=(
const nullable<T2&>& lhs,
const T2* rhs)
543 return lhs.m_value != rhs;
546 template<
typename T2>
547 bool operator!=(
const T2* lhs,
const nullable<T2&>& rhs)
549 return lhs != rhs.m_value;
Convenient type for char array storage and/or buffer with std::string compatibility.
Definition basetypes.h:30
Alternative to std::optional that supports reference (but not pointer) types.
Definition nullable.h:24
nullable & operator*=(T value)
This is same as operator=(T value), but allows to avoid ambiguities or picking wrong overload.
Definition nullable.h:98
All classes, functions, types and enums of PoDoFo are members of these namespace.
Definition basetypes.h:13