[ox/std] Add Optional

This commit is contained in:
Gary Talent 2021-10-29 21:16:20 -05:00
parent 45d79e99e8
commit fa06821d90
3 changed files with 146 additions and 0 deletions

View File

@ -80,6 +80,7 @@ install(
memops.hpp
memory.hpp
new.hpp
optional.hpp
random.hpp
std.hpp
stddef.hpp

144
deps/ox/src/ox/std/optional.hpp vendored Normal file
View File

@ -0,0 +1,144 @@
/*
* Copyright 2015 - 2021 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "bit.hpp"
#include "initializerlist.hpp"
#include "iterator.hpp"
#include "new.hpp"
#include "types.hpp"
#include "utility.hpp"
namespace ox {
template<typename T, std::size_t buffSize = sizeof(T)>
class Optional {
private:
T *m_ptr = nullptr;
char m_data[buffSize];
public:
Optional() noexcept = default;
Optional(const Optional &other) {
if (m_ptr) {
m_ptr->~T();
}
if (other.m_ptr) {
m_ptr = new(m_data) T(*other.m_ptr);
} else {
m_ptr = nullptr;
}
}
Optional(const Optional &&other) noexcept {
if (m_ptr) {
m_ptr->~T();
}
if (other.m_ptr) {
m_ptr = new(m_data) T(std::move(*other.m_ptr));
} else {
m_ptr = nullptr;
}
}
template<typename U = T>
constexpr U *get() noexcept {
return m_ptr;
}
template<typename U = T>
constexpr const U *get() const noexcept {
return m_ptr;
}
constexpr T &operator*() & noexcept {
return m_ptr;
}
constexpr const T &operator*() const & noexcept {
return m_ptr;
}
constexpr T &&operator*() && noexcept {
return m_ptr;
}
constexpr const T &&operator*() const && noexcept {
return m_ptr;
}
constexpr T *operator->() noexcept {
return m_ptr;
}
constexpr const T *operator->() const noexcept {
return m_ptr;
}
Optional &operator=(const Optional &other) {
if (this == &other) {
return *this;
}
if (m_ptr) {
m_ptr->~T();
}
if (other.m_ptr) {
m_ptr = new(m_data) T(*other.m_ptr);
} else {
m_ptr = nullptr;
}
return *this;
}
Optional &operator=(Optional &&other) noexcept {
if (this == &other) {
return *this;
}
if (m_ptr) {
m_ptr->~T();
}
if (other.m_ptr) {
m_ptr = new(m_data) T(std::move(*other.m_ptr));
} else {
m_ptr = nullptr;
}
return *this;
}
template<class... Args>
constexpr T &emplace(Args &&...args) {
m_ptr = new (m_data) T(ox::forward<Args>(args)...);
return *m_ptr;
}
template<typename U, class... Args>
constexpr T &emplace_subclass(Args &&...args) {
static_assert(sizeof(U) <= buffSize, "Subclass is too large for this Optional");
m_ptr = new (m_data) U(ox::forward<Args>(args)...);
return *m_ptr;
}
[[nodiscard]]
constexpr bool has_value() const noexcept {
return m_ptr;
}
explicit constexpr operator bool() const noexcept {
return m_ptr;
}
constexpr void reset() noexcept {
get()->~T();
m_ptr = nullptr;
}
};
}

View File

@ -24,6 +24,7 @@
#include "memops.hpp"
#include "memory.hpp"
#include "new.hpp"
#include "optional.hpp"
#include "random.hpp"
#include "stacktrace.hpp"
#include "stddef.hpp"