feat(memory): add ToAddress and refactor the code with it

This commit is contained in:
Redstone1024 2024-11-01 15:11:45 +08:00
parent 1cfa252779
commit 9785326b18
12 changed files with 170 additions and 131 deletions

View File

@ -18,6 +18,7 @@ NAMESPACE_BEGIN(Testing)
void TestMemory()
{
TestAddress();
TestAlignment();
TestMemoryBuffer();
TestMemoryMalloc();
@ -29,6 +30,41 @@ void TestMemory()
TestInOutPointer();
}
NAMESPACE_UNNAMED_BEGIN
template <typename T>
struct TTestStructA
{
T* Pad;
T* Data;
TTestStructA(T* InData) : Pad(nullptr), Data(InData) { }
~TTestStructA() { delete Data; }
T** operator&() { return &Data; }
};
template <typename T>
int32 TestFunctionB(TTestStructA<T>*)
{
return 0;
}
template <typename T>
int32 TestFunctionB(T**)
{
return 1;
}
NAMESPACE_UNNAMED_END
void TestAddress()
{
TTestStructA<int32> ObjectA(new int32(3));
always_check(TestFunctionB(&ObjectA) == 1);
always_check(TestFunctionB(AddressOf(ObjectA)) == 0);
always_check(AddressOf(TestAddress) == &TestAddress);
}
void TestAlignment()
{
int32 Unaligned = 0xAAAA;

View File

@ -1510,40 +1510,8 @@ void TestPropagateConst()
}
}
NAMESPACE_UNNAMED_BEGIN
template <typename T>
struct TTestStructA
{
T* Pad;
T* Data;
TTestStructA(T* InData) : Pad(nullptr), Data(InData) { }
~TTestStructA() { delete Data; }
T** operator&() { return &Data; }
};
template <typename T>
int32 TestFunctionB(TTestStructA<T>* Ptr)
{
return 0;
}
template <typename T>
int32 TestFunctionB(T** Ptr)
{
return 1;
}
NAMESPACE_UNNAMED_END
void TestMiscTemplates()
{
TTestStructA<int32> ObjectA(new int32(3));
always_check(TestFunctionB(&ObjectA) == 1);
always_check(TestFunctionB(AddressOf(ObjectA)) == 0);
always_check(AddressOf(TestMiscTemplates) == &TestMiscTemplates);
struct FTestRetainedRef { explicit FTestRetainedRef(TRetainedRef<const int64> InRef) { } };
int64 IntA;

View File

@ -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)
{

View File

@ -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*>);
@ -174,7 +175,7 @@ public:
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 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; }

View 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

View File

@ -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;

View File

@ -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"
@ -46,6 +47,7 @@ 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 AddressOf(Value); }
FORCEINLINE constexpr TConstantIterator& operator++() { return *this; }
@ -90,6 +92,7 @@ public:
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; }
FORCEINLINE constexpr TConstantIterator& operator++() { return *this; }
@ -155,7 +158,7 @@ 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 ToAddress(Current); }
NODISCARD FORCEINLINE constexpr const TRemoveReference<T>& operator[](ptrdiff) const { return *this; }

View File

@ -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)

View File

@ -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"

View File

@ -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"

View File

@ -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;

View File

@ -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();