1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:48:11 +00:00
serenity/Userland/Libraries/LibJS/Heap/GCPtr.h
MacDue 66a428ae03 LibJS+LibWeb: Return non-const types from Ptr class operators
Even if the pointer value is const, the value they point to is not
necessarily const, so these functions should not add the qualifier.

This also removes the redundant non-const implementations of these
operators.
2022-11-19 14:37:31 +00:00

216 lines
4.3 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)
: 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*>)
: 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=(GCPtr<T> const& other)
{
m_ptr = const_cast<T*>(other.ptr());
return *this;
}
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)
: m_ptr(&const_cast<T&>(ptr))
{
}
GCPtr(T* ptr)
: m_ptr(ptr)
{
}
GCPtr(T const* ptr)
: 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(std::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 { return m_ptr; }
T& operator*() const { 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();
}
}