#pragma once #include "asl/integers.hpp" #include "asl/meta.hpp" #include "asl/utility.hpp" namespace asl { // @Todo Shitty span, improve this template struct span { static constexpr bool kIsDynamic = kLen < 0; using size_type = select_t; constexpr span(T* begin, isize_t len) requires kIsDynamic : m_begin{begin} , m_len{len} {} constexpr span(T* begin) requires (!kIsDynamic) : m_begin{begin} , m_len{} {} T* m_begin; ASL_NO_UNIQUE_ADDRESS size_type m_len; }; namespace ptr_internal { template struct void_metadata { using metadata = empty; using pointee = T; constexpr auto deref(pointee* ptr) { return ptr; } }; template struct array_metadata {}; template struct array_metadata { using metadata = isize_t; using pointee = T; constexpr auto deref(pointee* ptr) { return span(ptr, m_len); } isize_t m_len; }; template struct array_metadata { using metadata = empty; using pointee = T[N]; constexpr auto deref(pointee* ptr) { return span(static_cast(*ptr)); } }; template struct object_metadata { using metadata = empty; using pointee = T; constexpr auto deref(pointee* ptr) { return ptr; } }; template struct ptr_like_metadata { using metadata = empty; using pointee = un_ref_t>* const; constexpr auto deref(pointee* ptr) { return *ptr; } }; template constexpr auto select_ptr_metadata() { if constexpr (is_void) return id>{}; else if constexpr (is_array) return id>{}; else if constexpr (is_object) return id>{}; else return id>{}; } template using metadata = decltype(select_ptr_metadata())::type; } // namespace ptr_internal template concept ptr_metadata = requires (T metadata, typename T::pointee* ptr) { is_object; is_object; { metadata.deref(ptr) }; }; template class ptr { using meta = ptr_internal::metadata; static_assert(ptr_metadata); meta::pointee* m_ptr; ASL_NO_UNIQUE_ADDRESS meta m_meta; public: }; } // namespace asl