#pragma once #include "asl/integers.hpp" #include "asl/meta.hpp" #include "asl/utility.hpp" namespace asl { constexpr auto addr(auto&& ref) { return __builtin_addressof(ref); } namespace ptr_internal { template class object_meta { public: using pointee = T; using metadata = empty; }; template class void_meta { public: using pointee = T; using metadata = empty; }; template class array_meta; template class array_meta { public: using pointee = T[N]; using metadata = empty; }; template class array_meta { public: using pointee = T; using metadata = isize_t; }; template class ptr_like_meta { static_assert(is_func || is_ref); public: using pointee = as_raw_ptr_t; using metadata = empty; }; template constexpr auto get_meta() { if constexpr (is_object) { return object_meta{}; } else if constexpr (is_void) { return void_meta{}; } else if constexpr (is_array) { return array_meta{}; } else if constexpr (is_ref || is_func) { return ptr_like_meta{}; } } template using meta = decltype(get_meta()); } // namespace ptr_internal template concept is_ptr_metadata = requires { requires is_object || is_void || is_array; requires is_object; }; template class ptr final { using meta = ptr_internal::meta; static_assert(is_ptr_metadata); public: using pointee = meta::pointee; using metadata = meta::metadata; private: pointee* m_ptr = nullptr; ASL_NO_UNIQUE_ADDRESS metadata m_metadata; public: }; } // namespace asl