diff --git a/deps/ox/src/ox/std/CMakeLists.txt b/deps/ox/src/ox/std/CMakeLists.txt index aca844e4..5c797fff 100644 --- a/deps/ox/src/ox/std/CMakeLists.txt +++ b/deps/ox/src/ox/std/CMakeLists.txt @@ -80,6 +80,7 @@ install( memops.hpp memory.hpp new.hpp + optional.hpp random.hpp std.hpp stddef.hpp diff --git a/deps/ox/src/ox/std/optional.hpp b/deps/ox/src/ox/std/optional.hpp new file mode 100644 index 00000000..4c3e9b4f --- /dev/null +++ b/deps/ox/src/ox/std/optional.hpp @@ -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 +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 + constexpr U *get() noexcept { + return m_ptr; + } + + template + 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 + constexpr T &emplace(Args &&...args) { + m_ptr = new (m_data) T(ox::forward(args)...); + return *m_ptr; + } + + template + 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)...); + 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; + } + +}; + +} \ No newline at end of file diff --git a/deps/ox/src/ox/std/std.hpp b/deps/ox/src/ox/std/std.hpp index b0e800aa..ed30970f 100644 --- a/deps/ox/src/ox/std/std.hpp +++ b/deps/ox/src/ox/std/std.hpp @@ -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"