#pragma once #include "compat/assert.hpp" #include "compat/defs.hpp" #include #include #include namespace floormat { template class safe_ptr final { T* ptr; public: template requires requires (Ts&&... xs) { new T{Utility::forward(xs)...}; } safe_ptr(InPlaceInitT, Ts&&... args) noexcept: ptr{new T{Utility::forward(args)...}} {} explicit safe_ptr(T*&& ptr) noexcept: ptr{ptr} { fm_assert(ptr != nullptr); ptr = nullptr; } ~safe_ptr() noexcept { if (ptr) [[likely]] delete ptr; ptr = (T*)0xbadcafedeadbabe; } explicit safe_ptr(safe_ptr&& other) noexcept: ptr{other.ptr} { other.ptr = nullptr; } explicit safe_ptr() noexcept: ptr{new T{}} {} safe_ptr& operator=(safe_ptr&& other) noexcept { fm_assert(this != &other); if (ptr) [[likely]] delete ptr; ptr = other.ptr; other.ptr = nullptr; return *this; } fm_DECLARE_DELETED_COPY_ASSIGNMENT(safe_ptr); //explicit operator bool() const noexcept { return ptr != nullptr; } const T& operator*() const noexcept { return *ptr; } T& operator*() noexcept { return *ptr; } const T* operator->() const noexcept { return ptr; } T* operator->() noexcept { return ptr; } }; } // namespace floormat