prime/include/rstl/optional_object.hpp

71 lines
1.6 KiB
C++

#ifndef _RSTL_OPTIONAL_OBJECT
#define _RSTL_OPTIONAL_OBJECT
#include "types.h"
#include "rstl/construct.hpp"
namespace rstl {
struct optional_object_null {};
template < typename T >
class optional_object {
public:
optional_object() : m_valid(false) {}
optional_object(optional_object_null) : m_valid(false) {}
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) {
construct< T >(m_data, other.data());
}
}
~optional_object() { clear(); }
optional_object& operator=(const optional_object& other) {
if (this != &other) {
if (other.m_valid) {
assign(other.data());
} else {
clear();
}
}
return *this;
}
optional_object& operator=(const T& item) {
assign(item);
return *this;
}
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); }
bool valid() const { return m_valid; }
operator bool() const { return m_valid; } // replace with valid()?
void clear() {
if (m_valid) {
rstl::destroy(get_ptr());
}
m_valid = false;
}
T& operator*() { return data(); }
T* operator->() { return &data(); }
private:
u8 m_data[sizeof(T)];
bool m_valid ATTRIBUTE_ALIGN(4);
void assign(const T& item) {
if (!m_valid) {
construct(get_ptr(), item);
m_valid = true;
} else {
data() = item;
}
}
};
} // namespace rstl
#endif // _RSTL_OPTIONAL_OBJECT