ACF $AcfVersion:0$
TNullable.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR GPL-3.0-or-later OR LicenseRef-ACF-Commercial
2#pragma once
3
4
5// STL includes
6#include <algorithm>
7
8
9namespace istd
10{
11
12
19template <class T>
21{
22public:
23 TNullable();
24 TNullable(const T& value);
25 TNullable(T&& value);
26 ~TNullable();
27
35 bool IsValid() const;
36
50 bool IsNull() const;
51
64 bool HasValue() const;
65
70 const T* GetPtr() const;
71 T* GetPtr();
72
78 T& GetValue();
79 const T& GetValue() const;
80
84 void Reset();
85
95 T& Emplace();
96
116 void SetNull();
117
118 // operators
119 TNullable& operator=(const T& value);
121
122 // STL-compatibility methods
123 // access operators
124 const T* operator->() const;
125 T* operator->();
126 const T& operator*() const &;
127 T& operator*() &;
128 const T&& operator*() const &&;
129 T&& operator*() &&;
130
131 // set operators
132 TNullable& operator=( std::nullptr_t );
133 TNullable& operator=(const TNullable& other);
134
135 explicit operator bool() const;
136 bool has_value() const;
137
138 // value access
139 T& value() &;
140 const T& value() const &;
141 T&& value() &&;
142 const T&& value() const &&;
143 T value_or(const T& default_value) const;
144
145 void swap(TNullable& other );
146 void reset();
147 T& emplace();
148 T& emplace(T&& value)&&;
149
150 //Compare two TNullable objects
151 bool operator==(const TNullable& other) const;
152 bool operator!=(const TNullable& other) const;
153
154 //Compare a TNullable object with a nullptr
155 bool operator==(std::nullptr_t) const;
156 bool operator!=(std::nullptr_t) const;
157
158 //Compare a TNullable object with a value
159 bool operator==(const T& value) const;
160 bool operator!=(const T& value) const;
161
162private:
163 bool m_hasValue;
164 bool m_isNull;
165 bool m_isValid;
166 T* m_dataPtr;
167};
168
169
170// public methods
171
172template <class T>
174 :m_hasValue(false),
175 m_isNull(false),
176 m_isValid(false),
177 m_dataPtr(nullptr)
178{
179}
180
181
182template<class T>
183inline TNullable<T>::TNullable(const T& value)
184 :m_hasValue(true),
185 m_isNull(false),
186 m_isValid(true)
187{
188 m_dataPtr = new T;
189 *m_dataPtr = value;
190}
191
192
193template<class T>
194inline TNullable<T>::TNullable(T&& value)
195 :m_hasValue(true),
196 m_isNull(false),
197 m_isValid(true)
198{
199 m_dataPtr = new T;
200 *m_dataPtr = std::move(value);
201}
202
203
204template <class T>
206{
207 if (m_dataPtr != nullptr){
208 delete m_dataPtr;
209 }
210}
211
212
213template<class T>
214inline bool TNullable<T>::IsValid() const
215{
216 return m_isValid;
217}
218
219
220template<class T>
222{
223 return m_isNull;
224}
225
226
227template<class T>
229{
230 return m_hasValue;
231}
232
233
234template<class T>
235const T* TNullable<T>::GetPtr() const
236{
237 return m_dataPtr;
238}
239
240
241template<class T>
243{
244 return m_dataPtr;
245}
246
247
248template<class T>
250{
251 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
252
253 return *m_dataPtr;
254}
255
256
257template<class T>
259{
260 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
261
262 return *m_dataPtr;
263}
264
265template<class T>
267{
268 if (m_dataPtr != nullptr){
269 delete m_dataPtr;
270 }
271
272 m_isNull = false;
273 m_hasValue = false;
274 m_isValid = false;
275 m_dataPtr = nullptr;
276}
277
278template<class T>
280{
281 m_isNull = false;
282 m_hasValue = true;
283 m_isValid = true;
284 if (m_dataPtr != nullptr){
285 delete m_dataPtr;
286 }
287
288 m_dataPtr = new T;
289
290 return *m_dataPtr;
291}
292
293
294template<class T>
296{
297 Reset();
298 m_isNull = true;
299 m_isValid = true;
300}
301
302
303// operators
304
305template<class T>
307{
308 m_hasValue = true;
309 m_isNull = false;
310 m_isValid = true;
311 if (m_dataPtr != nullptr){
312 delete m_dataPtr;
313 }
314
315 m_dataPtr = new T;
316 *m_dataPtr = value;
317
318 return *this;
319}
320
321
322template<class T>
324{
325 m_hasValue = true;
326 m_isNull = false;
327 m_isValid = true;
328 if (m_dataPtr != nullptr){
329 delete m_dataPtr;
330 }
331
332 m_dataPtr = new T;
333 *m_dataPtr = std::move(value);
334
335 return *this;
336}
337
338
339// STL-compatibility methods
340// access operators
341
342template<class T>
344{
345 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
346
347 return m_dataPtr;
348}
349
350
351template<class T>
353{
354 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
355
356 return m_dataPtr;
357}
358
359
360template<class T>
361const T& TNullable<T>::operator*() const &
362{
363 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
364
365 return *m_dataPtr;
366}
367
368
369template<class T>
371{
372 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
373
374 return *m_dataPtr;
375}
376
377
378template<class T>
379const T&& TNullable<T>::operator*() const &&
380{
381 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
382
383 return std::move(*m_dataPtr);
384}
385
386
387template<class T>
389{
390 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
391
392 return std::move(*m_dataPtr);
393}
394
395
396template<class T>
398{
399 Reset();
400 m_isNull = true;
401 m_isValid = true;
402
403 return *this;
404}
405
406
407template<class T>
409{
410 if (m_dataPtr != nullptr){
411 delete m_dataPtr;
412 m_dataPtr = nullptr;
413 }
414 if (other.m_dataPtr != nullptr){
415 m_dataPtr = new T;
416 *m_dataPtr = *other.m_dataPtr;
417 }
418
419 m_hasValue = other.m_hasValue;
420 m_isNull = other.m_isNull;
421 m_isValid = other.m_isValid;
422
423 return *this;
424}
425
426
427template<class T>
429{
430 return m_hasValue;
431}
432
433
434template<class T>
436{
437 return m_hasValue;
438}
439
440
441template<class T>
443{
444 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
445
446 return *m_dataPtr;
447}
448
449
450template<class T>
451const T& TNullable<T>::value() const &
452{
453 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
454
455 return *m_dataPtr;
456}
457
458
459template<class T>
461{
462 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
463
464 return std::move(*m_dataPtr);
465}
466
467
468template<class T>
469const T&& TNullable<T>::value() const &&
470{
471 Q_ASSERT_X(!m_isNull && m_hasValue, __func__, "Access to uninitialized data");
472
473 return std::move(*m_dataPtr);
474}
475
476
477template<class T>
478T TNullable<T>::value_or(const T& default_value) const
479{
480 if (m_hasValue && !m_isNull){
481 return *m_dataPtr;
482 }
483
484 return default_value;
485}
486
487
488template<class T>
490{
491 std::swap(m_dataPtr, other.m_dataPtr);
492 std::swap(m_hasValue, other.m_hasValue);
493 std::swap(m_isNull, other.m_isNull);
494 std::swap(m_isValid, other.m_isValid);
495}
496
497
498template<class T>
500{
501 Reset();
502}
503
504
505template<class T>
507{
508 return Emplace();
509}
510
511
512template<class T>
514{
515 m_dataPtr = std::move(value);
516 m_hasValue = true;
517 m_isNull = false;
518 m_isValid = true;
519
520 return *m_dataPtr;
521}
522
523
524template<class T>
525bool TNullable<T>::operator==(const TNullable& other) const
526{
527 bool retVal = m_hasValue == other.m_hasValue && m_isNull == other.m_isNull && m_isValid == other.m_isValid;
528
529 if (retVal && (m_dataPtr != nullptr && other.m_dataPtr != nullptr)){
530 retVal = *m_dataPtr == *other.m_dataPtr;
531 }
532
533 return retVal;
534}
535
536
537template<class T>
538bool TNullable<T>::operator!=(const TNullable& other) const
539{
540 return (!operator==(other));
541}
542
543
544template<class T>
545bool TNullable<T>::operator==(std::nullptr_t) const
546{
547 return m_dataPtr == nullptr;
548}
549
550
551template<class T>
552bool TNullable<T>::operator!=(std::nullptr_t) const
553{
554 return m_dataPtr != nullptr;
555}
556
557
558template<class T>
559bool TNullable<T>::operator==(const T& value) const
560{
561 if (!m_hasValue || m_isNull){
562 Q_ASSERT_X(false, __func__, "Comnpare with uninitialized data");
563
564 return false;
565 }
566
567 return *m_dataPtr == value;
568}
569
570
571template<class T>
572bool TNullable<T>::operator!=(const T& value) const
573{
574 if (!m_hasValue || m_isNull){
575 Q_ASSERT_X(false, __func__, "Comnpare with uninitialized data");
576
577 return false;
578 }
579
580 return *m_dataPtr != value;
581}
582
583
584} // namespace istd
585
586
TNullable & operator=(const T &value)
Definition TNullable.h:306
void SetNull()
Destroys a containing value (if was set), and sets state of a container to NULL.
Definition TNullable.h:295
void Reset()
Resets a container and destroys a value.
Definition TNullable.h:266
const T * GetPtr() const
access the pointer of value
Definition TNullable.h:235
bool IsValid() const
Checks whether the container has been initialized with a value, even if it is a NULL value.
Definition TNullable.h:214
const T & operator*() const &
Definition TNullable.h:361
void swap(TNullable &other)
Definition TNullable.h:489
T & Emplace()
Initializes a container with a default value.
Definition TNullable.h:279
T & GetValue()
access the value
Definition TNullable.h:249
bool has_value() const
Definition TNullable.h:435
T value_or(const T &default_value) const
Definition TNullable.h:478
bool operator!=(const TNullable &other) const
Definition TNullable.h:538
bool operator==(const TNullable &other) const
Definition TNullable.h:525
bool HasValue() const
Checks whether the container has been initialized with a specific value.
Definition TNullable.h:228
const T * operator->() const
Definition TNullable.h:343
bool IsNull() const
Checks whether the container has been explicitly initialized with a NULL value.
Definition TNullable.h:221
Standard library.
Definition IComponent.h:17