AuroraRuntime/Include/Aurora/Memory/ExtendStlLikeSharedPtr.hpp

186 lines
4.3 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ExtendStlLikeSharedPtr.hpp
Date: 2022-1-25
Author: Reece
***/
#pragma once
namespace Aurora::Memory
{
namespace _detail
{
struct IPtrGet
{
virtual void *Get() = 0;
};
struct IPtrNoOpGet : IPtrGet
{
inline virtual void *Get() override
{
AU_THROW_STRING("ExSharedPointer Null Access Violation");
}
};
inline IPtrNoOpGet gNoop;
}
template<class TType_t, class Base_t>
struct ExSharedPtr : public Base_t
#if !defined(_AURORA_NULLEXPT_ENABLE_UB) && !defined(_AURORA_NULLEXPT_BRANCH)
, _detail::IPtrGet
#endif
{
using element_type = Base_t::element_type;
using weak_type = Base_t::weak_type;
using base_type = Base_t;
using Base_t::Base_t;
ExSharedPtr(Base_t &&in) : Base_t(in)
{
#if !defined(_AURORA_NULLEXPT_ENABLE_UB)
_cache();
#endif
}
ExSharedPtr(const Base_t &in) : Base_t(in)
{
#if !defined(_AURORA_NULLEXPT_ENABLE_UB)
_cache();
#endif
}
void swap(Base_t &r)
{
Base_t::swap(r);
#if !defined(_AURORA_NULLEXPT_ENABLE_UB)
_cache();
#endif
}
void reset()
{
Base_t::reset();
#if !defined(_AURORA_NULLEXPT_BRANCH)
ptr = &_detail::gNoop;
#endif
}
operator Base_t() const noexcept
{
return *this;
}
ExSharedPtr &operator =(const Base_t &in) noexcept
{
Base_t::operator=(in);
#if !defined(_AURORA_NULLEXPT_ENABLE_UB)
_cache();
#endif
return *this;
}
template<typename TType2_t = TType_t>
TType2_t &operator*() const
{
return *operator->();
}
template<typename TType2_t = TType_t>
TType2_t *operator->() const
{
#if defined(_AURORA_NULLEXPT_ENABLE_UB)
return Base_t::operator->();
#elif !defined(_AURORA_NULLEXPT_BRANCH)
return AuReinterpretCast<TType2_t>(ptr->Get());
#else
throwif();
return Base_t::operator->();
#endif
}
template<typename TType2_t = TType_t>
TType2_t &operator*()
{
return *operator->();
}
template<typename TType2_t = TType_t>
TType2_t *operator->()
{
#if defined(_AURORA_NULLEXPT_ENABLE_UB)
return Base_t::operator->();
#elif !defined(_AURORA_NULLEXPT_BRANCH)
return AuReinterpretCast<TType2_t>(ptr->Get());
#else
throwif();
return Base_t::operator->();
#endif
}
private:
#if !defined(_AURORA_NULLEXPT_BRANCH)
_detail::IPtrGet *ptr = this;
inline virtual void *Get() override
{
return Base_t::operator->();
}
auline void _cache()
{
if (Base_t::operator bool())
{
ptr = this;
}
else
{
ptr = &_detail::gNoop;
}
}
#else
auline void _cache()
{
cached = Base_t::operator bool();
}
auline void throwif() const
{
if (!cached) [[unlikely]]
{
if (!Base_t::operator bool()) [[likely]]
{
AU_THROW_STRING("ExSharedPointer Null Access Violation");
}
}
}
auline void throwif()
{
if (!cached) [[unlikely]]
{
cached = Base_t::operator bool();
if (!cached) [[likely]]
{
AU_THROW_STRING("ExSharedPointer Null Access Violation");
}
}
}
#endif
};
template<class TType_t, class Base_t>
struct ExSharedFromThis : Base_t
{
ExSharedPtr<TType_t, AURORA_RUNTIME_AU_SHARED_PTR<TType_t>> SharedFromThis()
{
return Base_t::shared_from_this();
}
};
}