/* * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include namespace GC { template class Ptr; template class Ref { public: Ref() = delete; Ref(T& ptr) : m_ptr(&ptr) { } template Ref(U& ptr) requires(IsConvertible) : m_ptr(&static_cast(ptr)) { } template Ref(Ref const& other) requires(IsConvertible) : m_ptr(other.ptr()) { } template Ref& operator=(Ref const& other) requires(IsConvertible) { m_ptr = static_cast(other.ptr()); return *this; } Ref& operator=(T& other) { m_ptr = &other; return *this; } template Ref& operator=(U& other) requires(IsConvertible) { m_ptr = &static_cast(other); return *this; } RETURNS_NONNULL T* operator->() const { return m_ptr; } [[nodiscard]] T& operator*() const { return *m_ptr; } RETURNS_NONNULL T* ptr() const { return m_ptr; } RETURNS_NONNULL operator T*() const { return m_ptr; } operator T&() const { return *m_ptr; } private: T* m_ptr { nullptr }; }; template class Ptr { public: constexpr Ptr() = default; Ptr(T& ptr) : m_ptr(&ptr) { } Ptr(T* ptr) : m_ptr(ptr) { } template Ptr(Ptr const& other) requires(IsConvertible) : m_ptr(other.ptr()) { } Ptr(Ref const& other) : m_ptr(other.ptr()) { } template Ptr(Ref const& other) requires(IsConvertible) : m_ptr(other.ptr()) { } Ptr(nullptr_t) : m_ptr(nullptr) { } template Ptr& operator=(Ptr const& other) requires(IsConvertible) { m_ptr = static_cast(other.ptr()); return *this; } Ptr& operator=(Ref const& other) { m_ptr = other.ptr(); return *this; } template Ptr& operator=(Ref const& other) requires(IsConvertible) { m_ptr = static_cast(other.ptr()); return *this; } Ptr& operator=(T& other) { m_ptr = &other; return *this; } template Ptr& operator=(U& other) requires(IsConvertible) { m_ptr = &static_cast(other); return *this; } Ptr& operator=(T* other) { m_ptr = other; return *this; } template Ptr& operator=(U* other) requires(IsConvertible) { m_ptr = static_cast(other); return *this; } T* operator->() const { ASSERT(m_ptr); return m_ptr; } [[nodiscard]] T& operator*() const { ASSERT(m_ptr); return *m_ptr; } T* ptr() const { return m_ptr; } explicit operator bool() const { return !!m_ptr; } bool operator!() const { return !m_ptr; } operator T*() const { return m_ptr; } private: T* m_ptr { nullptr }; }; // Non-Owning GC::Ptr template using RawPtr = Ptr; // Non-Owning Ref template using RawRef = Ref; template inline bool operator==(Ptr const& a, Ptr const& b) { return a.ptr() == b.ptr(); } template inline bool operator==(Ptr const& a, Ref const& b) { return a.ptr() == b.ptr(); } template inline bool operator==(Ref const& a, Ref const& b) { return a.ptr() == b.ptr(); } template inline bool operator==(Ref const& a, Ptr const& b) { return a.ptr() == b.ptr(); } } namespace AK { template struct Traits> : public DefaultTraits> { static unsigned hash(GC::Ptr const& value) { return Traits::hash(value.ptr()); } }; template struct Traits> : public DefaultTraits> { static unsigned hash(GC::Ref const& value) { return Traits::hash(value.ptr()); } }; }