2022-10-09 05:13:17 +00:00
|
|
|
#ifndef _RSTL_OPTIONAL_OBJECT
|
|
|
|
#define _RSTL_OPTIONAL_OBJECT
|
2022-04-10 00:17:06 +00:00
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
|
2022-08-09 23:03:51 +00:00
|
|
|
#include "rstl/construct.hpp"
|
2022-04-10 00:17:06 +00:00
|
|
|
|
|
|
|
namespace rstl {
|
2022-09-18 06:16:53 +00:00
|
|
|
struct optional_object_null {};
|
|
|
|
|
2022-04-10 00:17:06 +00:00
|
|
|
template < typename T >
|
|
|
|
class optional_object {
|
|
|
|
public:
|
2022-09-18 05:55:13 +00:00
|
|
|
optional_object() : m_valid(false) {}
|
2022-09-18 06:16:53 +00:00
|
|
|
optional_object(optional_object_null) : m_valid(false) {}
|
2022-09-18 05:55:13 +00:00
|
|
|
optional_object(const T& item) : m_valid(true) { rstl::construct< T >(m_data, item); }
|
|
|
|
optional_object(const optional_object& other) : m_valid(other.m_valid) {
|
|
|
|
if (other.m_valid) {
|
2022-10-05 00:16:03 +00:00
|
|
|
construct< T >(m_data, other.data());
|
2022-09-18 05:55:13 +00:00
|
|
|
}
|
|
|
|
}
|
2022-04-10 00:17:06 +00:00
|
|
|
~optional_object() { clear(); }
|
|
|
|
|
2022-10-05 00:16:03 +00:00
|
|
|
optional_object& operator=(const optional_object& other) {
|
|
|
|
if (this != &other) {
|
|
|
|
if (other.m_valid) {
|
|
|
|
assign(other.data());
|
|
|
|
} else {
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
2022-09-13 04:26:54 +00:00
|
|
|
optional_object& operator=(const T& item) {
|
|
|
|
assign(item);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2022-09-18 05:55:13 +00:00
|
|
|
T& data() { return *get_ptr(); }
|
|
|
|
const T& data() const { return *get_ptr(); }
|
|
|
|
T* get_ptr() { return reinterpret_cast< T* >(m_data); }
|
|
|
|
const T* get_ptr() const { return reinterpret_cast< const T* >(m_data); }
|
2023-10-19 17:07:37 +00:00
|
|
|
const bool valid() const { return m_valid; }
|
2022-09-18 05:55:13 +00:00
|
|
|
operator bool() const { return m_valid; } // replace with valid()?
|
2022-04-10 00:17:06 +00:00
|
|
|
void clear() {
|
2022-09-18 05:55:13 +00:00
|
|
|
if (m_valid) {
|
|
|
|
rstl::destroy(get_ptr());
|
|
|
|
}
|
|
|
|
m_valid = false;
|
2022-04-10 00:17:06 +00:00
|
|
|
}
|
|
|
|
|
2022-09-13 04:26:54 +00:00
|
|
|
T& operator*() { return data(); }
|
2022-10-05 00:16:03 +00:00
|
|
|
T* operator->() { return &data(); }
|
2022-10-20 16:32:57 +00:00
|
|
|
|
|
|
|
const T& operator*() const { return data(); }
|
|
|
|
const T* operator->() const { return &data(); }
|
2022-09-13 04:26:54 +00:00
|
|
|
|
2022-04-10 00:17:06 +00:00
|
|
|
private:
|
2022-10-09 05:37:23 +00:00
|
|
|
uchar m_data[sizeof(T)];
|
2022-09-18 17:51:07 +00:00
|
|
|
bool m_valid ATTRIBUTE_ALIGN(4);
|
2022-09-13 04:26:54 +00:00
|
|
|
|
|
|
|
void assign(const T& item) {
|
2022-09-18 05:55:13 +00:00
|
|
|
if (!m_valid) {
|
2022-10-05 00:16:03 +00:00
|
|
|
construct(get_ptr(), item);
|
2022-09-18 05:55:13 +00:00
|
|
|
m_valid = true;
|
2022-09-13 04:26:54 +00:00
|
|
|
} else {
|
|
|
|
data() = item;
|
|
|
|
}
|
|
|
|
}
|
2022-04-10 00:17:06 +00:00
|
|
|
};
|
|
|
|
} // namespace rstl
|
|
|
|
|
2022-10-09 05:13:17 +00:00
|
|
|
#endif // _RSTL_OPTIONAL_OBJECT
|