1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 18:28:12 +00:00
serenity/Userland/Libraries/LibJS/Heap/GCPtr.h
Matthew Olsson 17a528c49e LibJS: Temporarily disambiguate const-ness of GCPtr constructors
Without this change, using {Nonnull,}GCPtr<T const> would complain that
there are multiple constructors which resolve to the same type (T& and
T const&). This removes that disambiguation and allows us to slowly fix
all of the constness issues surrounding GCPtrs. This change will not be
necessary in the future as we will be able to remove all of the const
qualifiers from the Ptr classes (they'll be in the template type
instead).
2023-03-06 13:05:43 +00:00

233 lines
4.4 KiB
C++

/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Types.h>
namespace JS {
template<typename T>
class GCPtr;
template<typename T>
class NonnullGCPtr {
public:
NonnullGCPtr() = delete;
NonnullGCPtr(T& ptr)
: m_ptr(&ptr)
{
}
NonnullGCPtr(T const& ptr)
requires(!IsConst<T>)
: m_ptr(&const_cast<T&>(ptr))
{
}
template<typename U>
NonnullGCPtr(U& ptr)
requires(IsConvertible<U*, T*>)
: m_ptr(&static_cast<T&>(ptr))
{
}
template<typename U>
NonnullGCPtr(U const& ptr)
requires(IsConvertible<U*, T*> && !IsConst<T>)
: m_ptr(&const_cast<T&>(static_cast<T const&>(ptr)))
{
}
template<typename U>
NonnullGCPtr(NonnullGCPtr<U> ptr)
requires(IsConvertible<U*, T*>)
: m_ptr(ptr)
{
}
NonnullGCPtr& operator=(T const& other)
{
m_ptr = &const_cast<T&>(other);
return *this;
}
template<typename U>
NonnullGCPtr& operator=(U const& other)
requires(IsConvertible<U*, T*>)
{
m_ptr = &const_cast<T&>(static_cast<T const&>(other));
return *this;
}
template<typename U>
NonnullGCPtr& operator=(NonnullGCPtr<U> const& other)
requires(IsConvertible<U*, T*>)
{
m_ptr = const_cast<T*>(static_cast<T const*>(other.ptr()));
return *this;
}
T* operator->() const { return m_ptr; }
T& operator*() const { return *m_ptr; }
T* ptr() const { return m_ptr; }
operator T*() const { return m_ptr; }
operator T&() const { return *m_ptr; }
private:
T* m_ptr { nullptr };
};
template<typename T>
class GCPtr {
public:
GCPtr() = default;
GCPtr(T& ptr)
: m_ptr(&ptr)
{
}
GCPtr(T const& ptr)
requires(!IsConst<T>)
: m_ptr(&const_cast<T&>(ptr))
{
}
GCPtr(T* ptr)
: m_ptr(ptr)
{
}
GCPtr(T const* ptr)
requires(!IsConst<T>)
: m_ptr(const_cast<T*>(ptr))
{
}
GCPtr(NonnullGCPtr<T> ptr)
: m_ptr(ptr)
{
}
template<typename U>
GCPtr(NonnullGCPtr<U> ptr)
requires(IsConvertible<U*, T*>)
: m_ptr(ptr)
{
}
GCPtr(nullptr_t)
: m_ptr(nullptr)
{
}
GCPtr(GCPtr const&) = default;
GCPtr& operator=(GCPtr const&) = default;
template<typename U>
GCPtr& operator=(GCPtr<U> const& other)
requires(IsConvertible<U*, T*>)
{
m_ptr = const_cast<T*>(static_cast<T const*>(other.ptr()));
return *this;
}
GCPtr& operator=(NonnullGCPtr<T> const& other)
{
m_ptr = const_cast<T*>(other.ptr());
return *this;
}
template<typename U>
GCPtr& operator=(NonnullGCPtr<U> const& other)
requires(IsConvertible<U*, T*>)
{
m_ptr = const_cast<T*>(static_cast<T const*>(other.ptr()));
return *this;
}
GCPtr& operator=(T const& other)
{
m_ptr = &const_cast<T&>(other);
return *this;
}
template<typename U>
GCPtr& operator=(U const& other)
requires(IsConvertible<U*, T*>)
{
m_ptr = &const_cast<T&>(static_cast<T const&>(other));
return *this;
}
GCPtr& operator=(T const* other)
{
m_ptr = const_cast<T*>(other);
return *this;
}
template<typename U>
GCPtr& operator=(U const* other)
requires(IsConvertible<U*, T*>)
{
m_ptr = const_cast<T*>(static_cast<T const*>(other));
return *this;
}
T* operator->() const
{
VERIFY(m_ptr);
return m_ptr;
}
T& operator*() const
{
VERIFY(m_ptr);
return *m_ptr;
}
T* ptr() const { return m_ptr; }
operator bool() const { return !!m_ptr; }
bool operator!() const { return !m_ptr; }
operator T*() const { return m_ptr; }
private:
T* m_ptr { nullptr };
};
template<typename T, typename U>
inline bool operator==(GCPtr<T> const& a, GCPtr<U> const& b)
{
return a.ptr() == b.ptr();
}
template<typename T, typename U>
inline bool operator==(GCPtr<T> const& a, NonnullGCPtr<U> const& b)
{
return a.ptr() == b.ptr();
}
template<typename T, typename U>
inline bool operator==(NonnullGCPtr<T> const& a, NonnullGCPtr<U> const& b)
{
return a.ptr() == b.ptr();
}
template<typename T, typename U>
inline bool operator==(NonnullGCPtr<T> const& a, GCPtr<U> const& b)
{
return a.ptr() == b.ptr();
}
}