From e50b9f5478edd3f0e6f9ac17d877632da8030a68 Mon Sep 17 00:00:00 2001 From: Jonne Ransijn Date: Sat, 26 Oct 2024 23:29:40 +0200 Subject: [PATCH] AK: Add `NonnullRawPtr` abstraction It is a non-null `T*` with reference semantics. Or a `T&` whose address can be copied and re-assigned. Or a `NonnullRefPtr` whose memory is not managed. It can be useful when you want to store a reference in a data structure that needs to be copyable or assignable. --- AK/NonnullRawPtr.h | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 AK/NonnullRawPtr.h diff --git a/AK/NonnullRawPtr.h b/AK/NonnullRawPtr.h new file mode 100644 index 00000000000..fc4b9836833 --- /dev/null +++ b/AK/NonnullRawPtr.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2024, the Ladybird developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace AK { + +template +requires(!IsLvalueReference && !IsRvalueReference) class [[nodiscard]] NonnullRawPtr { +public: + using ValueType = T; + + NonnullRawPtr() = delete; + + NonnullRawPtr(T& other) + : m_ptr(&other) + { + } + + NonnullRawPtr(NonnullRawPtr const& other) + : m_ptr(other.m_ptr) + { + } + + NonnullRawPtr(NonnullRawPtr&& other) + : m_ptr(other.m_ptr) + { + } + + NonnullRawPtr& operator=(NonnullRawPtr const& other) + { + m_ptr = other.m_ptr; + + return *this; + } + + NonnullRawPtr& operator=(NonnullRawPtr&& other) + { + m_ptr = other.m_ptr; + + return *this; + } + + operator bool() const = delete; + bool operator!() const = delete; + + operator T&() { return *m_ptr; } + operator T const&() const { return *m_ptr; } + + [[nodiscard]] ALWAYS_INLINE T& value() { return *m_ptr; } + [[nodiscard]] ALWAYS_INLINE T const& value() const { return *m_ptr; } + + [[nodiscard]] ALWAYS_INLINE T& operator*() { return value(); } + [[nodiscard]] ALWAYS_INLINE T const& operator*() const { return value(); } + + ALWAYS_INLINE RETURNS_NONNULL T* operator->() { return &value(); } + ALWAYS_INLINE RETURNS_NONNULL T const* operator->() const { return &value(); } + +private: + T* m_ptr; +}; + +template +struct Traits> : public DefaultTraits> { + static unsigned hash(NonnullRawPtr const& handle) { return Traits::hash(handle); } +}; + +namespace Detail { +template +inline constexpr bool IsHashCompatible, T> = true; + +template +inline constexpr bool IsHashCompatible> = true; + +} + +} + +#if USING_AK_GLOBALLY +using AK::NonnullRawPtr; +#endif