From bd98e6ec9eebcb5025bb1f79b3dacf7624f9fdbb Mon Sep 17 00:00:00 2001 From: tyanmahou Date: Sun, 12 Nov 2023 23:18:04 +0900 Subject: [PATCH] add variant_ptr --- Re-Abyss/app/utils/Memory/variant_ptr.hpp | 97 +++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 Re-Abyss/app/utils/Memory/variant_ptr.hpp diff --git a/Re-Abyss/app/utils/Memory/variant_ptr.hpp b/Re-Abyss/app/utils/Memory/variant_ptr.hpp new file mode 100644 index 00000000..acbd8468 --- /dev/null +++ b/Re-Abyss/app/utils/Memory/variant_ptr.hpp @@ -0,0 +1,97 @@ +#include +#include +#include + +namespace abyss +{ + template... Deriveds> + class variant_ptr + { + public: + variant_ptr() noexcept = default; + template requires std::same_as || (std::same_as || ...) + variant_ptr(Type * ptr) noexcept + { + if (ptr == nullptr) { + return; + } + const auto& rtti = typeid(*ptr); + if (rtti == typeid(Type)) [[likely]] { + m_ptr = ptr; + return; + } + Base* base = static_cast(ptr); + if (rtti == typeid(Base)) { + m_ptr = base; + return; + } + auto derived_checks = [&](T*) { + if (rtti == typeid(T)) { + if constexpr (std::convertible_to) { + m_ptr = static_cast(base); + return true; + } else { + m_ptr = dynamic_cast(base); + return true; + } + } + return false; + }; + if ((derived_checks(static_cast(nullptr)) || ...)) { + return; + } + m_ptr = ptr; + } + variant_ptr(const variant_ptr& other) noexcept : + m_ptr(other.m_ptr) + {} + variant_ptr(variant_ptr&& other) noexcept : + m_ptr(std::move(other.m_ptr)) + {} + variant_ptr(std::nullptr_t) noexcept : + m_ptr() + {} + Base* get() const noexcept + { + return cast_to(); + } + Base* operator ->() const noexcept + { + return get(); + } + Base& operator *() const noexcept + { + return *get(); + } + template requires std::is_pointer_v && (std::convertible_to || (std::convertible_to || ...)) + ToPtr cast_to() const noexcept + { + return std::visit([](T * ptr)->ToPtr { + if constexpr (std::convertible_to) { + return static_cast(ptr); + } else { + return nullptr; + } + }, m_ptr); + } + explicit operator bool() const noexcept + { + return get() != nullptr; + } + private: + std::variant m_ptr; + }; + template + struct variant_dynamic_cast_impl + { + template... Deriveds> + requires std::is_pointer_v && (std::convertible_to || (std::convertible_to || ...)) + ToPtr operator()(const variant_ptr& ptr) const noexcept + { + return ptr.template cast_to(); + } + }; + + template + inline constexpr auto variant_dynamic_cast = variant_dynamic_cast_impl{}; +}