114 lines
3.5 KiB
C++
114 lines
3.5 KiB
C++
#pragma once
|
|
|
|
#include <Core/Common/CoreUtils.h>
|
|
|
|
namespace Juliet
|
|
{
|
|
template <typename Type, typename OtherType>
|
|
concept NonNullPtr_Convertible = std::is_convertible_v<OtherType*, Type*>;
|
|
|
|
template <typename Type, typename OtherType>
|
|
concept NonNullPtr_SameType = std::is_same_v<OtherType*, Type*>;
|
|
|
|
template <typename Type>
|
|
class NonNullPtr
|
|
{
|
|
public:
|
|
constexpr NonNullPtr(Type* ptr)
|
|
: InternalPtr(ptr)
|
|
{
|
|
Assert(ptr, "Tried to initialize a NonNullPtr with a null pointer");
|
|
}
|
|
|
|
template <typename OtherType>
|
|
requires NonNullPtr_Convertible<OtherType*, Type*>
|
|
constexpr NonNullPtr(const NonNullPtr<OtherType>& otherPtr)
|
|
: InternalPtr(otherPtr.Get())
|
|
{
|
|
Assert(InternalPtr, "Fatal Error: Assigned a non null ptr using another NonNullPtr but its was null.");
|
|
}
|
|
|
|
// Assignment
|
|
[[nodiscard]] constexpr NonNullPtr& operator=(Type* ptr)
|
|
{
|
|
Assert(ptr, "Tried to assign a null pointer to a NonNullPtr!");
|
|
InternalPtr = ptr;
|
|
return *this;
|
|
}
|
|
|
|
template <typename OtherType>
|
|
requires NonNullPtr_Convertible<OtherType*, Type*>
|
|
[[nodiscard]] constexpr NonNullPtr& operator=(const NonNullPtr<OtherType>& otherPtr)
|
|
{
|
|
InternalPtr = otherPtr.Get();
|
|
return *this;
|
|
}
|
|
|
|
// Accessors
|
|
[[nodiscard]] constexpr operator Type*() const
|
|
{
|
|
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
return InternalPtr;
|
|
}
|
|
|
|
[[nodiscard]] constexpr Type* Get() const
|
|
{
|
|
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
return InternalPtr;
|
|
}
|
|
|
|
[[nodiscard]] constexpr Type& operator*() const
|
|
{
|
|
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
return *InternalPtr;
|
|
}
|
|
|
|
[[nodiscard]] constexpr Type* operator->() const
|
|
{
|
|
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
return InternalPtr;
|
|
}
|
|
|
|
// Comparisons
|
|
[[nodiscard]] constexpr bool operator==(const NonNullPtr& otherPtr) const
|
|
{
|
|
return InternalPtr == otherPtr.InternalPtr;
|
|
}
|
|
|
|
template <typename OtherType>
|
|
requires NonNullPtr_SameType<Type, OtherType>
|
|
[[nodiscard]] constexpr bool operator==(OtherType* otherRawPtr) const
|
|
{
|
|
return InternalPtr == otherRawPtr;
|
|
}
|
|
|
|
template <typename OtherType>
|
|
requires NonNullPtr_SameType<Type, OtherType>
|
|
[[nodiscard]] constexpr friend bool operator==(OtherType* otherRawPtr, const NonNullPtr& nonNullPtr)
|
|
{
|
|
return otherRawPtr == nonNullPtr.InternalPtr;
|
|
}
|
|
|
|
// Forbid assigning a nullptr at compile time
|
|
constexpr NonNullPtr(std::nullptr_t)
|
|
: InternalPtr(nullptr)
|
|
{
|
|
static_assert(sizeof(Type) == 0, "Trying to initialize a NonNullPtr with a nullptr value");
|
|
}
|
|
|
|
[[nodiscard]] constexpr NonNullPtr& operator=(std::nullptr_t)
|
|
{
|
|
static_assert(sizeof(Type) == 0, "Trying to assign a NonNullPtr with a nullptr value");
|
|
return *this;
|
|
}
|
|
|
|
[[nodiscard]] constexpr explicit operator bool() const { return InternalPtr != nullptr; }
|
|
|
|
private:
|
|
Type* InternalPtr;
|
|
};
|
|
|
|
template <typename T>
|
|
NonNullPtr(T*) -> NonNullPtr<T>;
|
|
} // namespace Juliet
|