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