Compare commits

...

4 Commits

9 changed files with 307 additions and 239 deletions

View File

@ -291,9 +291,9 @@ void TestUniquePointer()
TUniqueRef<FCounter, FDeleter> TempB(PtrB); TUniqueRef<FCounter, FDeleter> TempB(PtrB);
TUniqueRef<FCounter, FDeleter> TempC(PtrC, FDeleter()); TUniqueRef<FCounter, FDeleter> TempC(PtrC, FDeleter());
always_check(TempA == PtrA); always_check(TempA != nullptr);
always_check(TempC != TempB); always_check(TempC != TempB);
always_check((TempA <=> PtrA) == strong_ordering::equal); always_check((TempA <=> nullptr) == strong_ordering::greater);
always_check((TempC <=> TempB) != strong_ordering::equal); always_check((TempC <=> TempB) != strong_ordering::equal);
int32 TempNum; int32 TempNum;
@ -344,9 +344,9 @@ void TestUniquePointer()
TUniqueRef<FCounter[], FArrayDeleter> TempB(PtrB); TUniqueRef<FCounter[], FArrayDeleter> TempB(PtrB);
TUniqueRef<FCounter[], FArrayDeleter> TempC(PtrC, FArrayDeleter()); TUniqueRef<FCounter[], FArrayDeleter> TempC(PtrC, FArrayDeleter());
always_check(TempA == PtrA); always_check(TempA != nullptr);
always_check(TempC != TempB); always_check(TempC != TempB);
always_check((TempA <=> PtrA) == strong_ordering::equal); always_check((TempA <=> nullptr) == strong_ordering::greater);
always_check((TempC <=> TempB) != strong_ordering::equal); always_check((TempC <=> TempB) != strong_ordering::equal);
int32 TempNum; int32 TempNum;
@ -379,12 +379,6 @@ void TestUniquePointer()
always_check( FCounter::Num == 0); always_check( FCounter::Num == 0);
always_check(FArrayDeleter::Num == 4); always_check(FArrayDeleter::Num == 4);
{
TUniquePtr<int32> Temp = MakeUnique<int32>(NoInit);
*Temp = 15;
always_check(*Temp.Get() = 15);
}
{ {
TUniquePtr<int32> Temp = MakeUnique<int32>(); TUniquePtr<int32> Temp = MakeUnique<int32>();
*Temp = 15; *Temp = 15;
@ -403,9 +397,9 @@ void TestUniquePointer()
TUniquePtr<FCounter, FDeleter> TempB(PtrB); TUniquePtr<FCounter, FDeleter> TempB(PtrB);
TUniquePtr<FCounter, FDeleter> TempC(PtrC, FDeleter()); TUniquePtr<FCounter, FDeleter> TempC(PtrC, FDeleter());
always_check(TempA == PtrA); always_check(TempA != nullptr);
always_check(TempC != TempB); always_check(TempC != TempB);
always_check((TempA <=> PtrA) == strong_ordering::equal); always_check((TempA <=> nullptr) == strong_ordering::greater);
always_check((TempC <=> TempB) != strong_ordering::equal); always_check((TempC <=> TempB) != strong_ordering::equal);
int32 TempNum; int32 TempNum;
@ -450,12 +444,6 @@ void TestUniquePointer()
always_check(FCounter::Num == 0); always_check(FCounter::Num == 0);
always_check(FDeleter::Num == 4); always_check(FDeleter::Num == 4);
{
TUniquePtr<int32[]> Temp = MakeUnique<int32[]>(4, NoInit);
Temp[0] = 15;
always_check(Temp.Get()[0] = 15);
}
{ {
TUniquePtr<int32[]> Temp = MakeUnique<int32[]>(4); TUniquePtr<int32[]> Temp = MakeUnique<int32[]>(4);
Temp[0] = 15; Temp[0] = 15;
@ -474,9 +462,9 @@ void TestUniquePointer()
TUniquePtr<FCounter[], FArrayDeleter> TempB(PtrB); TUniquePtr<FCounter[], FArrayDeleter> TempB(PtrB);
TUniquePtr<FCounter[], FArrayDeleter> TempC(PtrC, FArrayDeleter()); TUniquePtr<FCounter[], FArrayDeleter> TempC(PtrC, FArrayDeleter());
always_check(TempA == PtrA); always_check(TempA != nullptr);
always_check(TempC != TempB); always_check(TempC != TempB);
always_check((TempA <=> PtrA) == strong_ordering::equal); always_check((TempA <=> nullptr) == strong_ordering::greater);
always_check((TempC <=> TempB) != strong_ordering::equal); always_check((TempC <=> TempB) != strong_ordering::equal);
int32 TempNum; int32 TempNum;
@ -552,9 +540,9 @@ void TestSharedPointer()
TSharedRef<FCounter> TempB(PtrB, FDeleter()); TSharedRef<FCounter> TempB(PtrB, FDeleter());
TSharedRef<FCounter> TempC(PtrC, FDeleter()); TSharedRef<FCounter> TempC(PtrC, FDeleter());
always_check(TempA == PtrA); always_check(TempA != nullptr);
always_check(TempC != TempB); always_check(TempC != TempB);
always_check((TempA <=> PtrA) == strong_ordering::equal); always_check((TempA <=> nullptr) == strong_ordering::greater);
always_check((TempC <=> TempB) != strong_ordering::equal); always_check((TempC <=> TempB) != strong_ordering::equal);
int32 TempNum; int32 TempNum;
@ -581,12 +569,6 @@ void TestSharedPointer()
always_check(FCounter::Num == 0); always_check(FCounter::Num == 0);
always_check(FDeleter::Num == 4); always_check(FDeleter::Num == 4);
{
TSharedRef<int32[]> Temp = MakeShared<int32[]>(4, NoInit);
Temp[0] = 15;
always_check(Temp.Get()[0] = 15);
}
{ {
TSharedRef<int32[]> Temp = MakeShared<int32[]>(4); TSharedRef<int32[]> Temp = MakeShared<int32[]>(4);
Temp[0] = 15; Temp[0] = 15;
@ -605,9 +587,9 @@ void TestSharedPointer()
TSharedRef<FCounter[]> TempB(PtrB, FArrayDeleter()); TSharedRef<FCounter[]> TempB(PtrB, FArrayDeleter());
TSharedRef<FCounter[]> TempC(PtrC, FArrayDeleter()); TSharedRef<FCounter[]> TempC(PtrC, FArrayDeleter());
always_check(TempA == PtrA); always_check(TempA != nullptr);
always_check(TempC != TempB); always_check(TempC != TempB);
always_check((TempA <=> PtrA) == strong_ordering::equal); always_check((TempA <=> nullptr) == strong_ordering::greater);
always_check((TempC <=> TempB) != strong_ordering::equal); always_check((TempC <=> TempB) != strong_ordering::equal);
int32 TempNum; int32 TempNum;
@ -646,9 +628,9 @@ void TestSharedPointer()
TSharedPtr<FCounter> TempB(PtrB, FDeleter()); TSharedPtr<FCounter> TempB(PtrB, FDeleter());
TSharedPtr<FCounter> TempC(PtrC, FDeleter()); TSharedPtr<FCounter> TempC(PtrC, FDeleter());
always_check(TempA == PtrA); always_check(TempA != nullptr);
always_check(TempC != TempB); always_check(TempC != TempB);
always_check((TempA <=> PtrA) == strong_ordering::equal); always_check((TempA <=> nullptr) == strong_ordering::greater);
always_check((TempC <=> TempB) != strong_ordering::equal); always_check((TempC <=> TempB) != strong_ordering::equal);
int32 TempNum; int32 TempNum;
@ -684,12 +666,6 @@ void TestSharedPointer()
always_check(FCounter::Num == 0); always_check(FCounter::Num == 0);
always_check(FDeleter::Num == 5); always_check(FDeleter::Num == 5);
{
TSharedPtr<int32[]> Temp = MakeShared<int32[]>(4, NoInit);
Temp[0] = 15;
always_check(Temp.Get()[0] = 15);
}
{ {
TSharedPtr<int32[]> Temp = MakeShared<int32[]>(4); TSharedPtr<int32[]> Temp = MakeShared<int32[]>(4);
Temp[0] = 15; Temp[0] = 15;
@ -708,9 +684,9 @@ void TestSharedPointer()
TSharedPtr<FCounter[]> TempB(PtrB, FArrayDeleter()); TSharedPtr<FCounter[]> TempB(PtrB, FArrayDeleter());
TSharedPtr<FCounter[]> TempC(PtrC, FArrayDeleter()); TSharedPtr<FCounter[]> TempC(PtrC, FArrayDeleter());
always_check(TempA == PtrA); always_check(TempA != nullptr);
always_check(TempC != TempB); always_check(TempC != TempB);
always_check((TempA <=> PtrA) == strong_ordering::equal); always_check((TempA <=> nullptr) == strong_ordering::greater);
always_check((TempC <=> TempB) != strong_ordering::equal); always_check((TempC <=> TempB) != strong_ordering::equal);
int32 TempNum; int32 TempNum;

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Memory/Allocator.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "Templates/TypeHash.h" #include "Templates/TypeHash.h"
#include "Templates/Container.h" #include "Templates/Container.h"
@ -9,8 +10,6 @@
#include "Miscellaneous/Compare.h" #include "Miscellaneous/Compare.h"
#include "Memory/MemoryOperator.h" #include "Memory/MemoryOperator.h"
#include "Memory/ObserverPointer.h" #include "Memory/ObserverPointer.h"
#include "Memory/DefaultAllocator.h"
#include "Memory/AllocatorInterface.h"
#include "Miscellaneous/AssertionMacros.h" #include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN NAMESPACE_REDCRAFT_BEGIN
@ -198,6 +197,9 @@ public:
using Iterator = NAMESPACE_PRIVATE::TArrayIterator<TArray, ElementType>; using Iterator = NAMESPACE_PRIVATE::TArrayIterator<TArray, ElementType>;
using ConstIterator = NAMESPACE_PRIVATE::TArrayIterator<TArray, const ElementType>; using ConstIterator = NAMESPACE_PRIVATE::TArrayIterator<TArray, const ElementType>;
using ReverseIterator = TReverseIterator< Iterator>;
using ConstReverseIterator = TReverseIterator<ConstIterator>;
static_assert(CContiguousIterator< Iterator>); static_assert(CContiguousIterator< Iterator>);
static_assert(CContiguousIterator<ConstIterator>); static_assert(CContiguousIterator<ConstIterator>);
@ -1125,6 +1127,12 @@ public:
NODISCARD FORCEINLINE constexpr Iterator End() { return Iterator(this, Storage.GetPointer() + Num()); } NODISCARD FORCEINLINE constexpr Iterator End() { return Iterator(this, Storage.GetPointer() + Num()); }
NODISCARD FORCEINLINE constexpr ConstIterator End() const { return ConstIterator(this, Storage.GetPointer() + Num()); } NODISCARD FORCEINLINE constexpr ConstIterator End() const { return ConstIterator(this, Storage.GetPointer() + Num()); }
/** @return The reverse iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() { return MakeReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr ConstReverseIterator RBegin() const { return MakeReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr ReverseIterator REnd() { return MakeReverseIterator(Begin()); }
NODISCARD FORCEINLINE constexpr ConstReverseIterator REnd() const { return MakeReverseIterator(Begin()); }
/** @return The number of elements in the container. */ /** @return The number of elements in the container. */
NODISCARD FORCEINLINE constexpr size_t Num() const { return Storage.GetNum(); } NODISCARD FORCEINLINE constexpr size_t Num() const { return Storage.GetNum(); }

View File

@ -128,6 +128,83 @@ concept CContiguousIterator = CRandomAccessIterator<I> && CLValueReference<TIter
static_assert(CContiguousIterator<int32*>); static_assert(CContiguousIterator<int32*>);
/** A iterator adaptor for reverse-order traversal. */
template <CBidirectionalIterator I>
class TReverseIterator
{
public:
using IteratorType = I;
using ElementType = TIteratorElementType<I>;
FORCEINLINE constexpr TReverseIterator() = default;
FORCEINLINE constexpr TReverseIterator(const TReverseIterator&) = default;
FORCEINLINE constexpr TReverseIterator(TReverseIterator&&) = default;
FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator&) = default;
FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&&) = default;
FORCEINLINE constexpr explicit TReverseIterator(IteratorType InValue) : Current(InValue) { }
template <typename J> requires (!CSameAs<IteratorType, J> && CConvertibleTo<const J&, IteratorType>)
FORCEINLINE constexpr TReverseIterator(const TReverseIterator<J>& InValue) : Current(InValue.Current) { }
template <typename J> requires (!CSameAs<IteratorType, J> && CConvertibleTo<const J&, IteratorType> && CAssignableFrom<IteratorType&, const J&>)
FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator<J>& InValue) { Current = InValue.Current; return *this; }
NODISCARD friend FORCEINLINE constexpr bool operator==(const TReverseIterator& LHS, const TReverseIterator& RHS) { return LHS.Current == RHS.Current; }
NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult<IteratorType> operator<=>(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CRandomAccessIterator<IteratorType>) { return RHS.Current <=> LHS.Current; }
NODISCARD FORCEINLINE constexpr ElementType& operator*() const { IteratorType Temp = Current; return *--Temp; }
NODISCARD FORCEINLINE constexpr ElementType* operator->() const { return AddressOf(operator*()); }
NODISCARD FORCEINLINE constexpr ElementType& operator[](ptrdiff Index) const requires (CRandomAccessIterator<IteratorType>) { return Current[-Index - 1]; }
FORCEINLINE constexpr TReverseIterator& operator++() { --Current; return *this; }
FORCEINLINE constexpr TReverseIterator& operator--() { ++Current; return *this; }
FORCEINLINE constexpr TReverseIterator operator++(int) { TReverseIterator Temp = *this; --Current; return Temp; }
FORCEINLINE constexpr TReverseIterator operator--(int) { TReverseIterator Temp = *this; ++Current; return Temp; }
FORCEINLINE constexpr TReverseIterator& operator+=(ptrdiff Offset) requires (CRandomAccessIterator<IteratorType>) { Current -= Offset; return *this; }
FORCEINLINE constexpr TReverseIterator& operator-=(ptrdiff Offset) requires (CRandomAccessIterator<IteratorType>) { Current += Offset; return *this; }
NODISCARD friend FORCEINLINE constexpr TReverseIterator operator+(TReverseIterator Iter, ptrdiff Offset) requires (CRandomAccessIterator<IteratorType>) { TReverseIterator Temp = Iter; Temp += Offset; return Temp; }
NODISCARD friend FORCEINLINE constexpr TReverseIterator operator+(ptrdiff Offset, TReverseIterator Iter) requires (CRandomAccessIterator<IteratorType>) { TReverseIterator Temp = Iter; Temp += Offset; return Temp; }
NODISCARD FORCEINLINE constexpr TReverseIterator operator-(ptrdiff Offset) const requires (CRandomAccessIterator<IteratorType>) { return TReverseIterator(Current + Offset); }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CRandomAccessIterator<IteratorType>) { return TReverseIterator(RHS.Current - LHS.Current); }
NODISCARD FORCEINLINE constexpr IteratorType GetBase() { return Current; }
NODISCARD FORCEINLINE constexpr const IteratorType GetBase() const { return Current; }
private:
IteratorType Current;
template <CBidirectionalIterator J>
friend class TReverseIterator;
};
static_assert(CRandomAccessIterator<TReverseIterator<int32*>>);
template <typename I>
TReverseIterator(I) -> TReverseIterator<I>;
/** Creates a TReverseIterator of type inferred from the argument. */
template <typename I>
constexpr TReverseIterator<I> MakeReverseIterator(I Iter)
{
return TReverseIterator<I>(Iter);
}
template <typename I, typename J> requires (!CSizedSentinelFor<I, J>)
inline constexpr bool bDisableSizedSentinelFor<TReverseIterator<I>, TReverseIterator<J>> = true;
NAMESPACE_BEGIN(Iteration) NAMESPACE_BEGIN(Iteration)
/** Increments given iterator 'Iter' by 'N' elements. */ /** Increments given iterator 'Iter' by 'N' elements. */
@ -195,9 +272,9 @@ template <typename T, size_t N> FORCEINLINE constexpr T* Begin( T(&&
template <typename T, size_t N> FORCEINLINE constexpr const T* Begin(const T(& Container)[N]) { return Container; } template <typename T, size_t N> FORCEINLINE constexpr const T* Begin(const T(& Container)[N]) { return Container; }
template <typename T, size_t N> FORCEINLINE constexpr const T* Begin(const T(&& Container)[N]) { return Container; } template <typename T, size_t N> FORCEINLINE constexpr const T* Begin(const T(&& Container)[N]) { return Container; }
/** Overloads the Begin algorithm for T::begin(). */ /** Overloads the Begin algorithm for initializer_list. */
template <typename T> requires (requires(T&& Container) { { Container.begin() } -> CForwardIterator; }) template <typename T>
FORCEINLINE constexpr decltype(auto) Begin(T&& Container) FORCEINLINE constexpr decltype(auto) Begin(initializer_list<T> Container)
{ {
return Container.begin(); return Container.begin();
} }
@ -215,13 +292,53 @@ template <typename T, size_t N> FORCEINLINE constexpr T* End( T(&& Co
template <typename T, size_t N> FORCEINLINE constexpr const T* End(const T(& Container)[N]) { return Container + N; } template <typename T, size_t N> FORCEINLINE constexpr const T* End(const T(& Container)[N]) { return Container + N; }
template <typename T, size_t N> FORCEINLINE constexpr const T* End(const T(&& Container)[N]) { return Container + N; } template <typename T, size_t N> FORCEINLINE constexpr const T* End(const T(&& Container)[N]) { return Container + N; }
/** Overloads the End algorithm for T::end(). */ /** Overloads the End algorithm for initializer_list. */
template <typename T> requires (requires(T&& Container) { { Container.end() } -> CForwardIterator; }) template <typename T>
FORCEINLINE constexpr decltype(auto) End(T&& Container) FORCEINLINE constexpr decltype(auto) End(initializer_list<T> Container)
{ {
return Container.end(); return Container.end();
} }
/** @return The reverse iterator to the beginning of a container. */
template <typename T> requires (requires(T&& Container) { { Container.RBegin() } -> CForwardIterator; })
FORCEINLINE constexpr decltype(auto) RBegin(T&& Container)
{
return Container.RBegin();
}
/** Overloads the RBegin algorithm for arrays. */
template <typename T, size_t N> FORCEINLINE constexpr decltype(auto) RBegin( T(& Container)[N]) { return MakeReverseIterator(End(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr decltype(auto) RBegin( T(&& Container)[N]) { return MakeReverseIterator(End(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr decltype(auto) RBegin(const T(& Container)[N]) { return MakeReverseIterator(End(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr decltype(auto) RBegin(const T(&& Container)[N]) { return MakeReverseIterator(End(Container)); }
/** Overloads the RBegin algorithm for T::rbegin(). */
template <typename T>
FORCEINLINE constexpr decltype(auto) RBegin(initializer_list<T> Container)
{
return MakeReverseIterator(Container.end());
}
/** @return The reverse iterator to the end of a container. */
template <typename T> requires (requires(T&& Container) { { Container.REnd() } -> CForwardIterator; })
FORCEINLINE constexpr decltype(auto) REnd(T&& Container)
{
return Container.REnd();
}
/** Overloads the REnd algorithm for arrays. */
template <typename T, size_t N> FORCEINLINE constexpr decltype(auto) REnd( T(& Container)[N]) { return MakeReverseIterator(Begin(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr decltype(auto) REnd( T(&& Container)[N]) { return MakeReverseIterator(Begin(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr decltype(auto) REnd(const T(& Container)[N]) { return MakeReverseIterator(Begin(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr decltype(auto) REnd(const T(&& Container)[N]) { return MakeReverseIterator(Begin(Container)); }
/** Overloads the REnd algorithm for T::end(). */
template <typename T>
FORCEINLINE constexpr decltype(auto) REnd(initializer_list<T> Container)
{
return MakeReverseIterator(Container.begin());
}
NAMESPACE_END(Iteration) NAMESPACE_END(Iteration)
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)

View File

@ -53,6 +53,71 @@ struct FAllocatorInterface
}; };
}; };
/** This is heap allocator that calls Memory::Malloc() directly for memory allocation. */
struct FHeapAllocator : public FAllocatorInterface
{
template <CObject T>
struct ForElementType : public FAllocatorInterface::ForElementType<T>
{
NODISCARD FORCEINLINE T* Allocate(size_t InNum)
{
return InNum != 0 ? static_cast<T*>(Memory::Malloc(Memory::QuantizeSize(InNum * sizeof(T)), alignof(T))) : nullptr;
}
FORCEINLINE void Deallocate(T* InPtr)
{
Memory::Free(InPtr);
}
NODISCARD FORCEINLINE constexpr size_t CalculateSlackGrow(size_t Num, size_t NumAllocated) const
{
const size_t FirstGrow = 4;
const size_t ConstantGrow = 16;
size_t Result;
check(Num > NumAllocated);
Result = (NumAllocated != 0) ? (Num + 3 * Num / 8 + ConstantGrow) : (Num > FirstGrow ? Num : FirstGrow);
Result = Memory::QuantizeSize(Result * sizeof(T), alignof(T)) / sizeof(T);
return Result;
}
NODISCARD FORCEINLINE constexpr size_t CalculateSlackShrink(size_t Num, size_t NumAllocated) const
{
size_t Result;
check(Num < NumAllocated);
const bool bTooManySlackBytes = (NumAllocated - Num) * sizeof(T) >= 16 * 1024;
const bool bTooManySlackElements = 3 * Num < 2 * NumAllocated;
const bool bNeedToShrink = (bTooManySlackBytes || bTooManySlackElements) && (NumAllocated - Num > 64 || Num == 0);
if (bNeedToShrink)
{
Result = Num != 0 ? Memory::QuantizeSize(Num * sizeof(T), alignof(T)) / sizeof(T) : 0;
}
else
{
Result = NumAllocated;
}
return Result;
}
NODISCARD FORCEINLINE constexpr size_t CalculateSlackReserve(size_t Num) const
{
return Num != 0 ? Memory::QuantizeSize(Num * sizeof(T), alignof(T)) / sizeof(T) : 0;
}
};
};
using FDefaultAllocator = FHeapAllocator;
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END NAMESPACE_REDCRAFT_END

View File

@ -1,15 +0,0 @@
#pragma once
#include "CoreTypes.h"
#include "Memory/Memory.h"
#include "Memory/HeapAllocator.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
using FDefaultAllocator = FHeapAllocator;
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -1,76 +0,0 @@
#pragma once
#include "CoreTypes.h"
#include "Memory/Memory.h"
#include "Memory/AllocatorInterface.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
/** This is heap allocator that calls Memory::Malloc() directly for memory allocation. */
struct FHeapAllocator : public FAllocatorInterface
{
template <CObject T>
struct ForElementType : public FAllocatorInterface::ForElementType<T>
{
NODISCARD FORCEINLINE T* Allocate(size_t InNum)
{
return InNum != 0 ? static_cast<T*>(Memory::Malloc(Memory::QuantizeSize(InNum * sizeof(T)), alignof(T))) : nullptr;
}
FORCEINLINE void Deallocate(T* InPtr)
{
Memory::Free(InPtr);
}
NODISCARD FORCEINLINE constexpr size_t CalculateSlackGrow(size_t Num, size_t NumAllocated) const
{
const size_t FirstGrow = 4;
const size_t ConstantGrow = 16;
size_t Result;
check(Num > NumAllocated);
Result = (NumAllocated != 0) ? (Num + 3 * Num / 8 + ConstantGrow) : (Num > FirstGrow ? Num : FirstGrow);
Result = Memory::QuantizeSize(Result * sizeof(T), alignof(T)) / sizeof(T);
return Result;
}
NODISCARD FORCEINLINE constexpr size_t CalculateSlackShrink(size_t Num, size_t NumAllocated) const
{
size_t Result;
check(Num < NumAllocated);
const bool bTooManySlackBytes = (NumAllocated - Num) * sizeof(T) >= 16 * 1024;
const bool bTooManySlackElements = 3 * Num < 2 * NumAllocated;
const bool bNeedToShrink = (bTooManySlackBytes || bTooManySlackElements) && (NumAllocated - Num > 64 || Num == 0);
if (bNeedToShrink)
{
Result = Num != 0 ? Memory::QuantizeSize(Num * sizeof(T), alignof(T)) / sizeof(T) : 0;
}
else
{
Result = NumAllocated;
}
return Result;
}
NODISCARD FORCEINLINE constexpr size_t CalculateSlackReserve(size_t Num) const
{
return Num != 0 ? Memory::QuantizeSize(Num * sizeof(T), alignof(T)) / sizeof(T) : 0;
}
};
};
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -241,10 +241,18 @@ class TSharedControllerWithObject final : public FSharedController
{ {
public: public:
FORCEINLINE explicit TSharedControllerWithObject(FNoInit) requires (!CConstructibleFrom<T, FNoInit>) { new (&Storage) T; } template <typename... Ts>
FORCEINLINE explicit TSharedControllerWithObject(Ts&&... Args)
template <typename... Ts> requires (CConstructibleFrom<T, Ts...>) {
FORCEINLINE explicit TSharedControllerWithObject(Ts&&... Args) { new (&Storage) T(Forward<Ts>(Args)...); } if constexpr (sizeof...(Ts) == 0)
{
new (&Storage) T;
}
else
{
new (&Storage) T(Forward<Ts>(Args)...);
}
}
virtual ~TSharedControllerWithObject() = default; virtual ~TSharedControllerWithObject() = default;
@ -263,20 +271,11 @@ class TSharedControllerWithArray final : public FSharedController
{ {
public: public:
static TSharedControllerWithArray* New(size_t N, FNoInit)
{
void* Buffer = Memory::Malloc(sizeof(TSharedControllerWithArray) + sizeof(T) * (N - 1), alignof(TSharedControllerWithArray));
const auto Controller = new (Buffer) TSharedControllerWithArray(N);
const T* ElementPtr = new (Controller->GetPointer()) T[N];
check(ElementPtr == Controller->GetPointer());
return Controller;
}
static TSharedControllerWithArray* New(size_t N) static TSharedControllerWithArray* New(size_t N)
{ {
void* Buffer = Memory::Malloc(sizeof(TSharedControllerWithArray) + sizeof(T) * (N - 1), alignof(TSharedControllerWithArray)); void* Buffer = Memory::Malloc(sizeof(TSharedControllerWithArray) + sizeof(T) * (N - 1), alignof(TSharedControllerWithArray));
const auto Controller = new (Buffer) TSharedControllerWithArray(N); const auto Controller = new (Buffer) TSharedControllerWithArray(N);
const T* ElementPtr = new (Controller->GetPointer()) T[N](); const T* ElementPtr = new (Controller->GetPointer()) T[N];
check(ElementPtr == Controller->GetPointer()); check(ElementPtr == Controller->GetPointer());
return Controller; return Controller;
} }
@ -637,16 +636,18 @@ public:
FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); } FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
/** Compares the pointer values of two TSharedRef. */ /** Compares the pointer values of two TSharedRef. */
NODISCARD friend FORCEINLINE constexpr bool operator==(const TSharedRef& LHS, const TSharedRef& RHS) { return LHS.Get() == RHS.Get(); } template <typename U> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr bool operator==(const TSharedRef& LHS, const TSharedRef<U>& RHS) { return LHS.Get() == RHS.Get(); }
/** Compares the pointer values of two TSharedRef. */ /** Compares the pointer values of two TSharedRef. */
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TSharedRef& LHS, const TSharedRef& RHS) { return LHS.Get() <=> RHS.Get(); } template <typename U> requires (CThreeWayComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TSharedRef& LHS, const TSharedRef<U>& RHS) { return LHS.Get() <=> RHS.Get(); }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
NODISCARD FORCEINLINE constexpr bool operator==(T* InPtr) const& { return Get() == InPtr; } NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& { return Get() == nullptr; }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(T* InPtr) const& { return Get() <=> InPtr; } NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(nullptr_t) const& { return Get() <=> static_cast<T*>(nullptr); }
/** TSharedRef cannot be initialized by nullptr. */ /** TSharedRef cannot be initialized by nullptr. */
void Reset(nullptr_t) = delete; void Reset(nullptr_t) = delete;
@ -674,7 +675,7 @@ public:
return ControllerWithDeleter != nullptr ? &ControllerWithDeleter->GetDeleter() : nullptr; return ControllerWithDeleter != nullptr ? &ControllerWithDeleter->GetDeleter() : nullptr;
} }
/** @return The a reference or pointer to the object owned by *this, i.e. Get(). */ /** @return The reference or pointer to the object owned by *this, i.e. Get(). */
NODISCARD FORCEINLINE constexpr T& operator*() const { return *Get(); } NODISCARD FORCEINLINE constexpr T& operator*() const { return *Get(); }
NODISCARD FORCEINLINE constexpr T* operator->() const { return Get(); } NODISCARD FORCEINLINE constexpr T* operator->() const { return Get(); }
@ -853,18 +854,18 @@ public:
FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); } FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
/** Compares the pointer values of two TSharedRef. */ /** Compares the pointer values of two TSharedRef. */
NODISCARD friend FORCEINLINE constexpr bool operator==(const TSharedRef& LHS, const TSharedRef& RHS) { return LHS.Get() == RHS.Get(); } template <typename U> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr bool operator==(const TSharedRef& LHS, const TSharedRef<U>& RHS) { return LHS.Get() == RHS.Get(); }
/** Compares the pointer values of two TSharedRef. */ /** Compares the pointer values of two TSharedRef. */
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TSharedRef& LHS, const TSharedRef& RHS) { return LHS.Get() <=> RHS.Get(); } template <typename U> requires (CThreeWayComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TSharedRef& LHS, const TSharedRef<U>& RHS) { return LHS.Get() <=> RHS.Get(); }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
template <typename U = T*> requires (CNullPointer<U> || (CPointer<U> && CConvertibleTo<TRemovePointer<U>(*)[], T(*)[]>)) NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& { return Get() == nullptr; }
NODISCARD FORCEINLINE constexpr bool operator==(U InPtr) const& { return Get() == InPtr; }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
template <typename U = T*> requires (CNullPointer<U> || (CPointer<U> && CConvertibleTo<TRemovePointer<U>(*)[], T(*)[]>)) NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(nullptr_t) const& { return Get() <=> static_cast<T*>(nullptr); }
NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(U InPtr) const& { return Get() <=> InPtr; }
/** TSharedRef cannot be initialized by nullptr. */ /** TSharedRef cannot be initialized by nullptr. */
void Reset(nullptr_t) = delete; void Reset(nullptr_t) = delete;
@ -1095,16 +1096,18 @@ public:
FORCEINLINE TSharedPtr& operator=(nullptr_t) { Reset(); return *this; } FORCEINLINE TSharedPtr& operator=(nullptr_t) { Reset(); return *this; }
/** Compares the pointer values of two TSharedPtr. */ /** Compares the pointer values of two TSharedPtr. */
NODISCARD friend FORCEINLINE constexpr bool operator==(const TSharedPtr& LHS, const TSharedPtr& RHS) { return LHS.Get() == RHS.Get(); } template <typename U> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr bool operator==(const TSharedPtr& LHS, const TSharedPtr<U>& RHS) { return LHS.Get() == RHS.Get(); }
/** Compares the pointer values of two TSharedPtr. */ /** Compares the pointer values of two TSharedPtr. */
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TSharedPtr& LHS, const TSharedPtr& RHS) { return LHS.Get() <=> RHS.Get(); } template <typename U> requires (CThreeWayComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TSharedPtr& LHS, const TSharedPtr<U>& RHS) { return LHS.Get() <=> RHS.Get(); }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
NODISCARD FORCEINLINE constexpr bool operator==(T* InPtr) const& { return Get() == InPtr; } NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& { return Get() == nullptr; }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(T* InPtr) const& { return Get() <=> InPtr; } NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(nullptr_t) const& { return Get() <=> static_cast<T*>(nullptr); }
/** Converts a shared pointer to a shared reference. The pointer MUST be valid or an assertion will trigger. */ /** Converts a shared pointer to a shared reference. The pointer MUST be valid or an assertion will trigger. */
FORCEINLINE TSharedRef<T> ToSharedRef() const& FORCEINLINE TSharedRef<T> ToSharedRef() const&
@ -1143,7 +1146,7 @@ public:
NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; } NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; }
NODISCARD FORCEINLINE constexpr explicit operator bool() const { return Get() != nullptr; } NODISCARD FORCEINLINE constexpr explicit operator bool() const { return Get() != nullptr; }
/** @return The a reference or pointer to the object owned by *this, i.e. Get(). */ /** @return The reference or pointer to the object owned by *this, i.e. Get(). */
NODISCARD FORCEINLINE constexpr T& operator*() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); } NODISCARD FORCEINLINE constexpr T& operator*() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); }
NODISCARD FORCEINLINE constexpr T* operator->() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); } NODISCARD FORCEINLINE constexpr T* operator->() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); }
@ -1361,18 +1364,18 @@ public:
FORCEINLINE TSharedPtr& operator=(nullptr_t) { Reset(); return *this; } FORCEINLINE TSharedPtr& operator=(nullptr_t) { Reset(); return *this; }
/** Compares the pointer values of two TSharedPtr. */ /** Compares the pointer values of two TSharedPtr. */
NODISCARD friend FORCEINLINE constexpr bool operator==(const TSharedPtr& LHS, const TSharedPtr& RHS) { return LHS.Get() == RHS.Get(); } template <typename U> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr bool operator==(const TSharedPtr& LHS, const TSharedPtr<U>& RHS) { return LHS.Get() == RHS.Get(); }
/** Compares the pointer values of two TSharedPtr. */ /** Compares the pointer values of two TSharedPtr. */
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TSharedPtr& LHS, const TSharedPtr& RHS) { return LHS.Get() <=> RHS.Get(); } template <typename U> requires (CThreeWayComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TSharedPtr& LHS, const TSharedPtr<U>& RHS) { return LHS.Get() <=> RHS.Get(); }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
template <typename U = T*> requires (CNullPointer<U> || (CPointer<U> && CConvertibleTo<TRemovePointer<U>(*)[], T(*)[]>)) NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& { return Get() == nullptr; }
NODISCARD FORCEINLINE constexpr bool operator==(U InPtr) const& { return Get() == InPtr; }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
template <typename U = T*> requires (CNullPointer<U> || (CPointer<U> && CConvertibleTo<TRemovePointer<U>(*)[], T(*)[]>)) NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(nullptr_t) const& { return Get() <=> static_cast<T*>(nullptr); }
NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(U InPtr) const& { return Get() <=> InPtr; }
/** Converts a shared pointer to a shared reference. The pointer MUST be valid or an assertion will trigger. */ /** Converts a shared pointer to a shared reference. The pointer MUST be valid or an assertion will trigger. */
FORCEINLINE TSharedRef<T[]> ToSharedRef() const& FORCEINLINE TSharedRef<T[]> ToSharedRef() const&
@ -1748,14 +1751,6 @@ private:
}; };
/** Constructs an object of type T and wraps it in a TSharedRef or TSharedPtr. Without initialization. */
template <typename T> requires (CObject<T> && !CArray<T> && !CConstructibleFrom<T, FNoInit> && CDestructible<T>)
NODISCARD FORCEINLINE NAMESPACE_PRIVATE::TSharedProxy<T> MakeShared(FNoInit)
{
const auto Controller = new NAMESPACE_PRIVATE::TSharedControllerWithObject<T>(NoInit);
return NAMESPACE_PRIVATE::TSharedProxy<T>(Controller->GetPointer(), Controller);
}
/** Constructs an object of type T and wraps it in a TSharedRef or TSharedPtr. */ /** Constructs an object of type T and wraps it in a TSharedRef or TSharedPtr. */
template <typename T, typename... Ts> requires (CObject<T> && !CArray<T> && CConstructibleFrom<T, Ts...> && CDestructible<T>) template <typename T, typename... Ts> requires (CObject<T> && !CArray<T> && CConstructibleFrom<T, Ts...> && CDestructible<T>)
NODISCARD FORCEINLINE NAMESPACE_PRIVATE::TSharedProxy<T> MakeShared(Ts&&... Args) NODISCARD FORCEINLINE NAMESPACE_PRIVATE::TSharedProxy<T> MakeShared(Ts&&... Args)
@ -1764,14 +1759,6 @@ NODISCARD FORCEINLINE NAMESPACE_PRIVATE::TSharedProxy<T> MakeShared(Ts&&... Args
return NAMESPACE_PRIVATE::TSharedProxy<T>(Controller->GetPointer(), Controller); return NAMESPACE_PRIVATE::TSharedProxy<T>(Controller->GetPointer(), Controller);
} }
/** Constructs an array of type T and wraps it in a TSharedRef or TSharedPtr. Without initialization. */
template <typename T> requires (CUnboundedArray<T> && CDefaultConstructible<TRemoveExtent<T>> && CDestructible<TRemoveExtent<T>>)
NODISCARD FORCEINLINE NAMESPACE_PRIVATE::TSharedProxy<T> MakeShared(size_t N, FNoInit)
{
const auto Controller = NAMESPACE_PRIVATE::TSharedControllerWithArray<TRemoveExtent<T>>::New(N, NoInit);
return NAMESPACE_PRIVATE::TSharedProxy<T>(Controller->GetPointer(), Controller);
}
/** Constructs an array of type T and wraps it in a TSharedRef or TSharedPtr. */ /** Constructs an array of type T and wraps it in a TSharedRef or TSharedPtr. */
template <typename T> requires (CUnboundedArray<T> && CDefaultConstructible<TRemoveExtent<T>> && CDestructible<TRemoveExtent<T>>) template <typename T> requires (CUnboundedArray<T> && CDefaultConstructible<TRemoveExtent<T>> && CDestructible<TRemoveExtent<T>>)
NODISCARD FORCEINLINE NAMESPACE_PRIVATE::TSharedProxy<T> MakeShared(size_t N) NODISCARD FORCEINLINE NAMESPACE_PRIVATE::TSharedProxy<T> MakeShared(size_t N)

View File

@ -177,16 +177,18 @@ public:
FORCEINLINE constexpr ~TUniqueRef() { Invoke(GetDeleter(), Get()); } FORCEINLINE constexpr ~TUniqueRef() { Invoke(GetDeleter(), Get()); }
/** Compares the pointer values of two TUniqueRef. */ /** Compares the pointer values of two TUniqueRef. */
NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniqueRef& LHS, const TUniqueRef& RHS) { return LHS.Get() == RHS.Get(); } template <typename U, typename InE> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniqueRef& LHS, const TUniqueRef<U, InE>& RHS) { return LHS.Get() == RHS.Get(); }
/** Compares the pointer values of two TUniqueRef. */ /** Compares the pointer values of two TUniqueRef. */
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TUniqueRef& LHS, const TUniqueRef& RHS) { return LHS.Get() <=> RHS.Get(); } template <typename U, typename InE> requires (CThreeWayComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TUniqueRef& LHS, const TUniqueRef<U, InE>& RHS) { return LHS.Get() <=> RHS.Get(); }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
NODISCARD FORCEINLINE constexpr bool operator==(T* InPtr) const& { return Get() == InPtr; } NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& { return Get() == nullptr; }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(T* InPtr) const& { return Get() <=> InPtr; } NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(nullptr_t) const& { return Get() <=> static_cast<T*>(nullptr); }
/** TUniqueRef cannot be reset to nullptr. */ /** TUniqueRef cannot be reset to nullptr. */
void Reset(nullptr_t) = delete; void Reset(nullptr_t) = delete;
@ -297,18 +299,18 @@ public:
FORCEINLINE constexpr ~TUniqueRef() { Invoke(GetDeleter(), Get()); } FORCEINLINE constexpr ~TUniqueRef() { Invoke(GetDeleter(), Get()); }
/** Compares the pointer values of two TUniqueRef. */ /** Compares the pointer values of two TUniqueRef. */
NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniqueRef& LHS, const TUniqueRef& RHS) { return LHS.Get() == RHS.Get(); } template <typename U, typename InE> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniqueRef& LHS, const TUniqueRef<U, InE>& RHS) { return LHS.Get() == RHS.Get(); }
/** Compares the pointer values of two TUniqueRef. */ /** Compares the pointer values of two TUniqueRef. */
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TUniqueRef& LHS, const TUniqueRef& RHS) { return LHS.Get() <=> RHS.Get(); } template <typename U, typename InE> requires (CThreeWayComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TUniqueRef& LHS, const TUniqueRef<U, InE>& RHS) { return LHS.Get() <=> RHS.Get(); }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
template <typename U = T> requires (CNullPointer<U> || (CPointer<U> && CConvertibleTo<TRemovePointer<U>(*)[], T(*)[]>)) NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& { return Get() == nullptr; }
NODISCARD FORCEINLINE constexpr bool operator==(U InPtr) const& { return Get() == InPtr; }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
template <typename U = T> requires (CNullPointer<U> || (CPointer<U> && CConvertibleTo<TRemovePointer<U>(*)[], T(*)[]>)) NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(nullptr_t) const& { return Get() <=> static_cast<T*>(nullptr); }
NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(U InPtr) const& { return Get() <=> InPtr; }
/** TUniqueRef cannot be reset to nullptr. */ /** TUniqueRef cannot be reset to nullptr. */
void Reset(nullptr_t) = delete; void Reset(nullptr_t) = delete;
@ -440,16 +442,18 @@ public:
FORCEINLINE constexpr TUniquePtr& operator=(nullptr_t) { Reset(); return *this; } FORCEINLINE constexpr TUniquePtr& operator=(nullptr_t) { Reset(); return *this; }
/** Compares the pointer values of two TUniquePtr. */ /** Compares the pointer values of two TUniquePtr. */
NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniquePtr& LHS, const TUniquePtr& RHS) { return LHS.Get() == RHS.Get(); } template <typename U, typename InE> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniquePtr& LHS, const TUniquePtr<U, InE>& RHS) { return LHS.Get() == RHS.Get(); }
/** Compares the pointer values of two TUniquePtr. */ /** Compares the pointer values of two TUniquePtr. */
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TUniquePtr& LHS, const TUniquePtr& RHS) { return LHS.Get() <=> RHS.Get(); } template <typename U, typename InE> requires (CThreeWayComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TUniquePtr& LHS, const TUniquePtr<U, InE>& RHS) { return LHS.Get() <=> RHS.Get(); }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
NODISCARD FORCEINLINE constexpr bool operator==(T* InPtr) const& { return Get() == InPtr; } NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& { return Get() == nullptr; }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(T* InPtr) const& { return Get() <=> InPtr; } NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(nullptr_t) const& { return Get() <=> static_cast<T*>(nullptr); }
/** Returns a pointer to the managed object and releases the ownership. */ /** Returns a pointer to the managed object and releases the ownership. */
NODISCARD FORCEINLINE constexpr T* Release() { return Exchange(Storage.GetPointer(), nullptr); } NODISCARD FORCEINLINE constexpr T* Release() { return Exchange(Storage.GetPointer(), nullptr); }
@ -577,18 +581,18 @@ public:
FORCEINLINE constexpr TUniquePtr& operator=(nullptr_t) { Reset(); return *this; } FORCEINLINE constexpr TUniquePtr& operator=(nullptr_t) { Reset(); return *this; }
/** Compares the pointer values of two TUniquePtr. */ /** Compares the pointer values of two TUniquePtr. */
NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniquePtr& LHS, const TUniquePtr& RHS) { return LHS.Get() == RHS.Get(); } template <typename U, typename InE> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniquePtr& LHS, const TUniquePtr<U, InE>& RHS) { return LHS.Get() == RHS.Get(); }
/** Compares the pointer values of two TUniquePtr. */ /** Compares the pointer values of two TUniquePtr. */
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TUniquePtr& LHS, const TUniquePtr& RHS) { return LHS.Get() <=> RHS.Get(); } template <typename U, typename InE> requires (CThreeWayComparable<T*, TRemoveExtent<U>*>)
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TUniquePtr& LHS, const TUniquePtr<U, InE>& RHS) { return LHS.Get() <=> RHS.Get(); }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
template <typename U = T*> requires (CNullPointer<U> || (CPointer<U> && CConvertibleTo<TRemovePointer<U>(*)[], T(*)[]>)) NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& { return Get() == nullptr; }
NODISCARD FORCEINLINE constexpr bool operator==(U InPtr) const& { return Get() == InPtr; }
/** Compares the pointer values with a raw pointer. */ /** Compares the pointer values with nullptr. */
template <typename U = T*> requires (CNullPointer<U> || (CPointer<U> && CConvertibleTo<TRemovePointer<U>(*)[], T(*)[]>)) NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(nullptr_t) const& { return Get() <=> static_cast<T*>(nullptr); }
NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(U InPtr) const& { return Get() <=> InPtr; }
/** Returns a pointer to the managed array and releases the ownership. */ /** Returns a pointer to the managed array and releases the ownership. */
NODISCARD FORCEINLINE constexpr T* Release() { return Exchange(Storage.GetPointer(), nullptr); } NODISCARD FORCEINLINE constexpr T* Release() { return Exchange(Storage.GetPointer(), nullptr); }
@ -659,21 +663,23 @@ private:
}; };
/** Constructs an object of type T and wraps it in a TUniquePtr. Without initialization. */
template <typename T> requires (CObject<T> && !CArray<T> && !CConstructibleFrom<T, FNoInit> && CDestructible<T>)
NODISCARD FORCEINLINE constexpr TUniquePtr<T> MakeUnique(FNoInit) { return TUniquePtr<T>(new T); }
/** Constructs an object of type T and wraps it in a TUniquePtr. */ /** Constructs an object of type T and wraps it in a TUniquePtr. */
template <typename T, typename... Ts> requires (CObject<T> && !CArray<T> && CConstructibleFrom<T, Ts...> && CDestructible<T>) template <typename T, typename... Ts> requires (CObject<T> && !CArray<T> && CConstructibleFrom<T, Ts...> && CDestructible<T>)
NODISCARD FORCEINLINE constexpr TUniquePtr<T> MakeUnique(Ts&&... Args) { return TUniquePtr<T>(new T(Forward<Ts>(Args)...)); } NODISCARD FORCEINLINE constexpr TUniquePtr<T> MakeUnique(Ts&&... Args)
{
/** Constructs an array of type T and wraps it in a TUniquePtr. Without initialization. */ if constexpr (sizeof...(Ts) == 0)
template <typename T> requires (CUnboundedArray<T> && CDefaultConstructible<TRemoveExtent<T>> && CDestructible<TRemoveExtent<T>>) {
NODISCARD FORCEINLINE constexpr TUniquePtr<T> MakeUnique(size_t N, FNoInit) { return TUniquePtr<T>(new TRemoveExtent<T>[N]); } return TUniquePtr<T>(new T);
}
else
{
return TUniquePtr<T>(new T(Forward<Ts>(Args)...));
}
}
/** Constructs an array of type T and wraps it in a TUniquePtr. */ /** Constructs an array of type T and wraps it in a TUniquePtr. */
template <typename T> requires (CUnboundedArray<T> && CDefaultConstructible<TRemoveExtent<T>> && CDestructible<TRemoveExtent<T>>) template <typename T> requires (CUnboundedArray<T> && CDefaultConstructible<TRemoveExtent<T>> && CDestructible<TRemoveExtent<T>>)
NODISCARD FORCEINLINE constexpr TUniquePtr<T> MakeUnique(size_t N) { return TUniquePtr<T>(new TRemoveExtent<T>[N]()); } NODISCARD FORCEINLINE constexpr TUniquePtr<T> MakeUnique(size_t N) { return TUniquePtr<T>(new TRemoveExtent<T>[N]); }
/** Construction of arrays of known bound is disallowed. */ /** Construction of arrays of known bound is disallowed. */
template <typename T, typename... Ts> requires (CBoundedArray<T>) template <typename T, typename... Ts> requires (CBoundedArray<T>)

View File

@ -245,14 +245,14 @@ public:
} }
/** Check if the optional value is equivalent to 'InValue'. */ /** Check if the optional value is equivalent to 'InValue'. */
template <typename T = OptionalType> requires (!CTOptional<T>&& CWeaklyEqualityComparable<OptionalType, T>) template <typename T = OptionalType> requires (!CTOptional<T> && CWeaklyEqualityComparable<OptionalType, T>)
NODISCARD FORCEINLINE constexpr bool operator==(const T& InValue) const& NODISCARD FORCEINLINE constexpr bool operator==(const T& InValue) const&
{ {
return IsValid() ? GetValue() == InValue : false; return IsValid() ? GetValue() == InValue : false;
} }
/** Check that the optional value is in ordered relationship with 'InValue'. */ /** Check that the optional value is in ordered relationship with 'InValue'. */
template <typename T = OptionalType> requires (!CTOptional<T>&& CSynthThreeWayComparable<OptionalType, T>) template <typename T = OptionalType> requires (!CTOptional<T> && CSynthThreeWayComparable<OptionalType, T>)
NODISCARD FORCEINLINE constexpr partial_ordering operator<=>(const T& InValue) const& NODISCARD FORCEINLINE constexpr partial_ordering operator<=>(const T& InValue) const&
{ {
return IsValid() ? SynthThreeWayCompare(GetValue(), InValue) : partial_ordering::unordered; return IsValid() ? SynthThreeWayCompare(GetValue(), InValue) : partial_ordering::unordered;