feat(memory): add ToAddress and refactor the code with it
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Memory/Address.h"
|
||||
#include "Memory/Allocator.h"
|
||||
#include "Containers/Array.h"
|
||||
#include "Templates/Utility.h"
|
||||
@ -58,7 +59,7 @@ public:
|
||||
{
|
||||
checkf(Extent == DynamicExtent || Extent == InCount, TEXT("Illegal range count. Please check InCount."));
|
||||
|
||||
Impl.Pointer = AddressOf(*InFirst);
|
||||
Impl.Pointer = ToAddress(InFirst);
|
||||
|
||||
if constexpr (Extent == DynamicExtent)
|
||||
{
|
||||
@ -72,7 +73,7 @@ public:
|
||||
{
|
||||
checkf(Extent == DynamicExtent || Extent == InLast - InFirst, TEXT("Illegal range iterator. Please check InLast - InFirst."));
|
||||
|
||||
Impl.Pointer = AddressOf(*InFirst);
|
||||
Impl.Pointer = ToAddress(InFirst);
|
||||
|
||||
if constexpr (Extent == DynamicExtent)
|
||||
{
|
||||
@ -84,7 +85,8 @@ public:
|
||||
template <size_t N> requires (Extent == DynamicExtent || N == Extent)
|
||||
FORCEINLINE constexpr TArrayView(ElementType(&InArray)[N])
|
||||
{
|
||||
Impl.Pointer = AddressOf(InArray[0]);
|
||||
// @TODO: Refactor this to use the GetData() function.
|
||||
Impl.Pointer = InArray;
|
||||
|
||||
if constexpr (Extent == DynamicExtent)
|
||||
{
|
||||
@ -114,7 +116,8 @@ public:
|
||||
{
|
||||
checkf(Extent == DynamicExtent || Extent == InValue.Num(), TEXT("Illegal view extent. Please check InValue.Num()."));
|
||||
|
||||
Impl.Pointer = AddressOf(InValue[0]);
|
||||
// @TODO: Refactor this to use the GetData() function.
|
||||
Impl.Pointer = InValue.GetData().Get();
|
||||
|
||||
if constexpr (Extent == DynamicExtent)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Memory/Address.h"
|
||||
#include "Templates/Invoke.h"
|
||||
#include "Templates/Utility.h"
|
||||
#include "Templates/Noncopyable.h"
|
||||
@ -128,7 +129,7 @@ concept CContiguousIterator = CRandomAccessIterator<I> && CLValueReference<TIter
|
||||
&& CSameAs<TIteratorElementType<I>, TRemoveCVRef<TIteratorReferenceType<I>>>
|
||||
&& requires(I& Iter)
|
||||
{
|
||||
{ AddressOf(*Iter) } -> CSameAs<TAddPointer<TIteratorReferenceType<I>>>;
|
||||
{ ToAddress(Iter) } -> CSameAs<TAddPointer<TIteratorReferenceType<I>>>;
|
||||
};
|
||||
|
||||
static_assert(CContiguousIterator<int32*>);
|
||||
@ -173,8 +174,8 @@ public:
|
||||
template <CBidirectionalIterator J> requires (CSizedSentinelFor<J, IteratorType>)
|
||||
NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult<J, IteratorType> operator<=>(const TReverseIterator& LHS, const TReverseIterator<J>& RHS) { return RHS.GetBase() <=> LHS.GetBase(); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr TIteratorReferenceType<IteratorType> operator*() const { IteratorType Temp = GetBase(); return *--Temp; }
|
||||
NODISCARD FORCEINLINE constexpr TIteratorPointerType<IteratorType> operator->() const { return AddressOf(operator*()); }
|
||||
NODISCARD FORCEINLINE constexpr TIteratorReferenceType<IteratorType> operator*() const { IteratorType Temp = GetBase(); return *--Temp; }
|
||||
NODISCARD FORCEINLINE constexpr TIteratorPointerType<IteratorType> operator->() const { IteratorType Temp = GetBase(); return ToAddress(--Temp); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr TIteratorReferenceType<IteratorType> operator[](ptrdiff Index) const requires (CRandomAccessIterator<IteratorType>) { return GetBase()[-Index - 1]; }
|
||||
|
||||
@ -402,7 +403,7 @@ public:
|
||||
|
||||
NODISCARD FORCEINLINE constexpr TIteratorReferenceType<IteratorType> operator*() const requires (CDereferenceable<const IteratorType>) { CheckThis(true); return *Current; }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr TIteratorPointerType<IteratorType> operator->() const requires (CContiguousIterator<IteratorType>) { CheckThis(true); return AddressOf(operator*()); }
|
||||
NODISCARD FORCEINLINE constexpr TIteratorPointerType<IteratorType> operator->() const requires (CContiguousIterator<IteratorType>) { CheckThis(true); return ToAddress(Current); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr TIteratorReferenceType<IteratorType> operator[](ptrdiff Index) const requires (CRandomAccessIterator<IteratorType>) { TCountedIterator Temp = *this + Index; return *Temp; }
|
||||
|
||||
|
43
Redcraft.Utility/Source/Public/Memory/Address.h
Normal file
43
Redcraft.Utility/Source/Public/Memory/Address.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Memory/PointerTraits.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
/** Obtains a raw pointer from a pointer-like type. */
|
||||
template <typename T> requires (TPointerTraits<T>::bIsPointer || requires(const T& Ptr) { Ptr.operator->(); })
|
||||
constexpr auto ToAddress(const T& Ptr) noexcept
|
||||
{
|
||||
if constexpr (TPointerTraits<T>::bIsPointer) {
|
||||
return TPointerTraits<T>::ToAddress(Ptr);
|
||||
}
|
||||
else {
|
||||
return ToAddress(Ptr.operator->());
|
||||
}
|
||||
}
|
||||
|
||||
/** Obtains the actual address of the object or function arg, even in presence of overloaded operator&. */
|
||||
template <typename T> requires (CObject<T>)
|
||||
FORCEINLINE constexpr T* AddressOf(T& Object)
|
||||
{
|
||||
return reinterpret_cast<T*>(&const_cast<char&>(reinterpret_cast<const volatile char&>(Object)));
|
||||
}
|
||||
|
||||
/** Obtains the actual address of the object or function arg, even in presence of overloaded operator&. */
|
||||
template <typename T> requires (!CObject<T>)
|
||||
FORCEINLINE constexpr T* AddressOf(T& Object)
|
||||
{
|
||||
return &Object;
|
||||
}
|
||||
|
||||
/** Rvalue overload is deleted to prevent taking the address of const rvalues. */
|
||||
template <typename T>
|
||||
const T* AddressOf(const T&&) = delete;
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
@ -7,7 +7,7 @@ NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
/** The class template provides the standardized way to access certain properties of pointer-like types. */
|
||||
template <typename T>
|
||||
template <typename>
|
||||
struct TPointerTraits
|
||||
{
|
||||
static constexpr bool bIsPointer = false;
|
||||
@ -21,7 +21,7 @@ struct TPointerTraits<T*>
|
||||
|
||||
using PointerType = T*;
|
||||
using ElementType = T;
|
||||
|
||||
|
||||
static FORCEINLINE constexpr ElementType* ToAddress(PointerType InPtr)
|
||||
{
|
||||
return InPtr;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Memory/Address.h"
|
||||
#include "Templates/Utility.h"
|
||||
#include "Containers/Iterator.h"
|
||||
#include "Miscellaneous/Compare.h"
|
||||
@ -45,7 +46,8 @@ public:
|
||||
|
||||
FORCEINLINE constexpr TConstantIterator& operator=(TConstantIterator&&) requires (CMoveAssignable<T>) = default;
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const T& operator*() const { return Value; }
|
||||
NODISCARD FORCEINLINE constexpr const T& operator*() const { return Value; }
|
||||
NODISCARD FORCEINLINE constexpr const T* operator->() const { return AddressOf(Value); }
|
||||
|
||||
FORCEINLINE constexpr TConstantIterator& operator++() { return *this; }
|
||||
|
||||
@ -89,7 +91,8 @@ public:
|
||||
template <typename U> requires (CConvertibleTo<U*, T*>)
|
||||
FORCEINLINE constexpr TConstantIterator& operator=(const TConstantIterator<U>& InValue) { Ptr = InValue.Ptr; return *this; }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const T& operator*() const { return *Ptr; }
|
||||
NODISCARD FORCEINLINE constexpr const T& operator*() const { return *Ptr; }
|
||||
NODISCARD FORCEINLINE constexpr const T* operator->() const { return Ptr; }
|
||||
|
||||
FORCEINLINE constexpr TConstantIterator& operator++() { return *this; }
|
||||
|
||||
@ -154,8 +157,8 @@ public:
|
||||
|
||||
NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(FDefaultSentinel) const& { return static_cast<ptrdiff>(0) <=> Length; }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const TRemoveReference<T>& operator*() const { CheckThis(true); return *Current; }
|
||||
NODISCARD FORCEINLINE constexpr const TRemoveReference<T>* operator->() const { CheckThis(true); return AddressOf(operator*()); }
|
||||
NODISCARD FORCEINLINE constexpr const TRemoveReference<T>& operator*() const { CheckThis(true); return *Current; }
|
||||
NODISCARD FORCEINLINE constexpr const TRemoveReference<T>* operator->() const { CheckThis(true); return ToAddress(Current); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const TRemoveReference<T>& operator[](ptrdiff) const { return *this; }
|
||||
|
||||
|
@ -117,22 +117,22 @@ public:
|
||||
FORCEINLINE TString& operator=(TString&& InValue) { NativeData = MoveTemp(InValue.NativeData); InValue.NativeData.PushBack(LITERAL(ElementType, '\0')); return *this; }
|
||||
|
||||
/** Compares the contents of two strings. */
|
||||
FORCEINLINE NODISCARD friend bool operator==(const TString& LHS, const TString& RHS) { return TStringView<ElementType>(LHS) == TStringView<ElementType>(RHS); }
|
||||
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, const TString& RHS) { return TStringView<ElementType>(LHS) == TStringView<ElementType>(RHS); }
|
||||
|
||||
/** Compares the contents of a string and a character. */
|
||||
FORCEINLINE NODISCARD friend bool operator==(const TString& LHS, ElementType RHS) { return TStringView<ElementType>(LHS) == RHS; }
|
||||
FORCEINLINE NODISCARD friend bool operator==(const TString& LHS, const ElementType* RHS) { return TStringView<ElementType>(LHS) == RHS; }
|
||||
FORCEINLINE NODISCARD friend bool operator==( ElementType LHS, const TString& RHS) { return LHS == TStringView<ElementType>(RHS); }
|
||||
FORCEINLINE NODISCARD friend bool operator==(const ElementType* LHS, const TString& RHS) { return LHS == TStringView<ElementType>(RHS); }
|
||||
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, ElementType RHS) { return TStringView<ElementType>(LHS) == RHS; }
|
||||
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, const ElementType* RHS) { return TStringView<ElementType>(LHS) == RHS; }
|
||||
NODISCARD friend FORCEINLINE bool operator==( ElementType LHS, const TString& RHS) { return LHS == TStringView<ElementType>(RHS); }
|
||||
NODISCARD friend FORCEINLINE bool operator==(const ElementType* LHS, const TString& RHS) { return LHS == TStringView<ElementType>(RHS); }
|
||||
|
||||
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
||||
FORCEINLINE NODISCARD friend auto operator<=>(const TString& LHS, const TString& RHS) { return TStringView<ElementType>(LHS) <=> TStringView<ElementType>(RHS); }
|
||||
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, const TString& RHS) { return TStringView<ElementType>(LHS) <=> TStringView<ElementType>(RHS); }
|
||||
|
||||
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
||||
FORCEINLINE NODISCARD friend auto operator<=>(const TString& LHS, ElementType RHS) { return TStringView<ElementType>(LHS) <=> RHS; }
|
||||
FORCEINLINE NODISCARD friend auto operator<=>(const TString& LHS, const ElementType* RHS) { return TStringView<ElementType>(LHS) <=> RHS; }
|
||||
FORCEINLINE NODISCARD friend auto operator<=>( ElementType LHS, const TString& RHS) { return LHS <=> TStringView<ElementType>(RHS); }
|
||||
FORCEINLINE NODISCARD friend auto operator<=>(const ElementType* LHS, const TString& RHS) { return LHS <=> TStringView<ElementType>(RHS); }
|
||||
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, ElementType RHS) { return TStringView<ElementType>(LHS) <=> RHS; }
|
||||
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, const ElementType* RHS) { return TStringView<ElementType>(LHS) <=> RHS; }
|
||||
NODISCARD friend FORCEINLINE auto operator<=>(ElementType LHS, const TString& RHS) { return LHS <=> TStringView<ElementType>(RHS); }
|
||||
NODISCARD friend FORCEINLINE auto operator<=>(const ElementType* LHS, const TString& RHS) { return LHS <=> TStringView<ElementType>(RHS); }
|
||||
|
||||
/** Inserts 'InValue' before 'Index' in the string. */
|
||||
FORCEINLINE Iterator Insert(size_t Index, ElementType InValue)
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Memory/Memory.h"
|
||||
#include "Memory/Address.h"
|
||||
#include "Templates/Meta.h"
|
||||
#include "Templates/Invoke.h"
|
||||
#include "Templates/Utility.h"
|
||||
@ -96,7 +97,7 @@ class alignas(16) TFunctionStorage<false, bIsUnique>
|
||||
public:
|
||||
|
||||
FORCEINLINE constexpr TFunctionStorage() = default;
|
||||
|
||||
|
||||
TFunctionStorage(const TFunctionStorage& InValue) requires (!bIsUnique)
|
||||
: RTTI(InValue.RTTI)
|
||||
{
|
||||
@ -151,7 +152,7 @@ public:
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
||||
TFunctionStorage& operator=(const TFunctionStorage& InValue) requires (!bIsUnique)
|
||||
{
|
||||
if (&InValue == this) UNLIKELY return *this;
|
||||
@ -322,7 +323,7 @@ private:
|
||||
|
||||
using FMoveConstruct = void(*)(void*, void*);
|
||||
using FDestruct = void(*)(void* );
|
||||
|
||||
|
||||
const FMoveConstruct MoveConstruct;
|
||||
const FDestruct Destruct;
|
||||
|
||||
@ -343,7 +344,7 @@ private:
|
||||
)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
struct FCopyableRTTI : public FMovableRTTI
|
||||
{
|
||||
using FCopyConstruct = void(*)(void*, const void*);
|
||||
@ -363,7 +364,7 @@ private:
|
||||
};
|
||||
|
||||
using FRTTI = TConditional<bIsUnique, FMovableRTTI, FCopyableRTTI>;
|
||||
|
||||
|
||||
static_assert(alignof(FRTTI) >= 4);
|
||||
|
||||
static constexpr uintptr_t RepresentationMask = 3;
|
||||
@ -375,7 +376,7 @@ private:
|
||||
Small = 2, // InternalStorage
|
||||
Big = 3, // ExternalStorage
|
||||
};
|
||||
|
||||
|
||||
union
|
||||
{
|
||||
uint8 InternalStorage[64 - sizeof(uintptr) - sizeof(uintptr)];
|
||||
@ -387,7 +388,7 @@ private:
|
||||
|
||||
FORCEINLINE constexpr ERepresentation GetRepresentation() const { return static_cast<ERepresentation>(RTTI & RepresentationMask); }
|
||||
FORCEINLINE constexpr const FRTTI& GetRTTI() const { return *reinterpret_cast<const FRTTI*>(RTTI & ~RepresentationMask); }
|
||||
|
||||
|
||||
FORCEINLINE constexpr void* GetStorage()
|
||||
{
|
||||
switch (GetRepresentation())
|
||||
@ -399,7 +400,7 @@ private:
|
||||
default: check_no_entry(); return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FORCEINLINE constexpr const void* GetStorage() const
|
||||
{
|
||||
switch (GetRepresentation())
|
||||
@ -461,7 +462,7 @@ public:
|
||||
|
||||
using ResultType = Ret;
|
||||
using ArgumentType = TTypeSequence<Ts...>;
|
||||
|
||||
|
||||
FORCEINLINE constexpr TFunctionImpl() = default;
|
||||
FORCEINLINE constexpr TFunctionImpl(const TFunctionImpl&) = default;
|
||||
FORCEINLINE constexpr TFunctionImpl(TFunctionImpl&&) = default;
|
||||
@ -648,7 +649,7 @@ public:
|
||||
{
|
||||
Impl::template Emplace<T>(Forward<Ts>(Args)...);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an TFunction with initial content an function object of type TDecay<T>,
|
||||
* direct-non-list-initialized from IL, Forward<Ts>(Args)....
|
||||
@ -694,7 +695,7 @@ public:
|
||||
Impl::Destroy();
|
||||
return Impl::template Emplace<T>(Forward<Ts>(Args)...);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Changes the function object to one of type TDecay<T> constructed from the arguments.
|
||||
* First destroys the current function object (if any) by Reset(), then constructs an object of type
|
||||
@ -790,7 +791,7 @@ public:
|
||||
if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Impl::Invalidate();
|
||||
else Impl::template Emplace<T>(Forward<T>(InValue));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an TUniqueFunction with initial content an function object of type TDecay<T>,
|
||||
* direct-non-list-initialized from Forward<Ts>(Args)....
|
||||
@ -801,7 +802,7 @@ public:
|
||||
{
|
||||
Impl::template Emplace<T>(Forward<Ts>(Args)...);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an TUniqueFunction with initial content an function object of type TDecay<T>,
|
||||
* direct-non-list-initialized from IL, Forward<Ts>(Args)....
|
||||
@ -844,7 +845,7 @@ public:
|
||||
using DecayedType = TDecay<T>;
|
||||
return Impl::template Emplace<T>(Forward<Ts>(Args)...);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Changes the function object to one of type TDecay<T> constructed from the arguments.
|
||||
* First destroys the current function object (if any) by Reset(), then constructs an object of type
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Memory/Address.h"
|
||||
#include "Templates/Invoke.h"
|
||||
#include "Templates/Utility.h"
|
||||
#include "Templates/Optional.h"
|
||||
@ -31,7 +32,7 @@ public:
|
||||
|
||||
/** Copies content of other into a new instance. */
|
||||
FORCEINLINE constexpr TReferenceWrapper(const TReferenceWrapper&) = default;
|
||||
|
||||
|
||||
/** Converting copy constructor. */
|
||||
template <typename T = ReferencedType> requires (CConvertibleTo<T&, ReferencedType&>)
|
||||
FORCEINLINE constexpr TReferenceWrapper(const TReferenceWrapper<T>& InValue)
|
||||
|
@ -89,24 +89,6 @@ FORCEINLINE constexpr T Exchange(T& A, U&& B)
|
||||
template <typename T>
|
||||
TAddRValueReference<T> DeclVal();
|
||||
|
||||
/** Obtains the actual address of the object or function arg, even in presence of overloaded operator&. */
|
||||
template <typename T> requires (CObject<T>)
|
||||
FORCEINLINE constexpr T* AddressOf(T& Object)
|
||||
{
|
||||
return reinterpret_cast<T*>(&const_cast<char&>(reinterpret_cast<const volatile char&>(Object)));
|
||||
}
|
||||
|
||||
/** Obtains the actual address of the object or function arg, even in presence of overloaded operator&. */
|
||||
template <typename T> requires (!CObject<T>)
|
||||
FORCEINLINE constexpr T* AddressOf(T& Object)
|
||||
{
|
||||
return &Object;
|
||||
}
|
||||
|
||||
/** Rvalue overload is deleted to prevent taking the address of const rvalues. */
|
||||
template <typename T>
|
||||
const T* AddressOf(const T&&) = delete;
|
||||
|
||||
struct FIgnore final
|
||||
{
|
||||
template <typename T>
|
||||
@ -116,7 +98,7 @@ struct FIgnore final
|
||||
/**
|
||||
* An object of unspecified type such that any value can be assigned to it with no effect.
|
||||
* Intended for use with Tie when unpacking a TTuple, as placeholders for unused arguments
|
||||
* or using Ignore to avoid warnings about unused return values from NODISCARD functions.
|
||||
* or using Ignore to avoid warnings about unused return values from NODISCARD functions.
|
||||
*/
|
||||
inline constexpr FIgnore Ignore;
|
||||
|
||||
@ -137,7 +119,7 @@ inline constexpr FIgnore Ignore;
|
||||
|
||||
/**
|
||||
* This class is used to create a set of overloaded functions.
|
||||
*
|
||||
*
|
||||
* Visit(TOverloaded {
|
||||
* [](auto A) { ... },
|
||||
* [](double A) { ... },
|
||||
|
@ -9,6 +9,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
|
||||
NAMESPACE_BEGIN(Testing)
|
||||
|
||||
REDCRAFTUTILITY_API void TestMemory();
|
||||
REDCRAFTUTILITY_API void TestAddress();
|
||||
REDCRAFTUTILITY_API void TestAlignment();
|
||||
REDCRAFTUTILITY_API void TestMemoryBuffer();
|
||||
REDCRAFTUTILITY_API void TestMemoryMalloc();
|
||||
|
Reference in New Issue
Block a user