实现对类型的基础内存操作

This commit is contained in:
_Redstone_c_ 2021-10-06 15:06:49 +08:00
parent 6e3c008936
commit 83be3aa142
6 changed files with 350 additions and 32 deletions

View File

@ -1,4 +1,5 @@
#pragma once
#include "CoreTypes.h"
#include "Templates/MemoryOps.h"
#include "Misc/AssertionMacros.h"

View File

@ -7,27 +7,27 @@
NS_REDCRAFT_BEGIN
NS_BEGIN(Memory)
void* Memmove(void* Dest, const void* Src, size_t Count)
FORCEINLINE void* Memmove(void* Dest, const void* Src, size_t Count)
{
return std::memmove(Dest, Src, Count);
}
int32 Memcmp(const void* Buf1, const void* Buf2, size_t Count)
FORCEINLINE int32 Memcmp(const void* Buf1, const void* Buf2, size_t Count)
{
return std::memcmp(Buf1, Buf2, Count);
}
void Memset(void* Dest, uint8 ValueToSet, size_t Count)
FORCEINLINE void Memset(void* Dest, uint8 ValueToSet, size_t Count)
{
std::memset(Dest, ValueToSet, Count);
}
void* Memzero(void* Dest, size_t Count)
FORCEINLINE void* Memzero(void* Dest, size_t Count)
{
return std::memset(Dest, 0, Count);
}
void* Memcpy(void* Dest, const void* Src, size_t Count)
FORCEINLINE void* Memcpy(void* Dest, const void* Src, size_t Count)
{
return std::memcpy(Dest, Src, Count);
}
@ -53,12 +53,12 @@ static FORCEINLINE void Memcpy(T& Dest, const T& Src)
Memcpy(&Dest, &Src, sizeof(T));
}
void* SystemMalloc(size_t Count)
FORCEINLINE void* SystemMalloc(size_t Count)
{
return std::malloc(Count);
}
void SystemFree(void* Ptr)
FORCEINLINE void SystemFree(void* Ptr)
{
std::free(Ptr);
}

View File

@ -0,0 +1,35 @@
#pragma once
#include "CoreTypes.h"
NS_REDCRAFT_BEGIN
NS_BEGIN(Memory)
template <typename ElementType, typename SizeType>
FORCEINLINE void DefaultConstructItems(void* Address, SizeType Count = 1);
template <typename ElementType, typename SizeType>
FORCEINLINE void DestructItems(ElementType* Element, SizeType Count = 1);
template <typename DestinationElementType, typename SourceElementType, typename SizeType>
FORCEINLINE void ConstructItems(void* Dest, const SourceElementType* Source, SizeType Count = 1);
template <typename ElementType, typename SizeType>
FORCEINLINE void CopyAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count = 1);
template <typename DestinationElementType, typename SourceElementType, typename SizeType>
FORCEINLINE void RelocateConstructItems(void* Dest, const SourceElementType* Source, SizeType Count = 1);
template <typename ElementType, typename SizeType>
FORCEINLINE void MoveConstructItems(void* Dest, const ElementType* Source, SizeType Count = 1);
template <typename ElementType, typename SizeType>
FORCEINLINE void MoveAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count = 1);
template <typename ElementType, typename SizeType>
FORCEINLINE bool CompareItems(const ElementType* A, const ElementType* B, SizeType Count = 1);
NS_END(Memory)
NS_REDCRAFT_END
#include "Templates/MemoryOps.inl"

View File

@ -0,0 +1,186 @@
#include "HAL/Memory.h"
#include "Templates/TypeTraits.h"
#include "MemoryOps.h"
NS_REDCRAFT_BEGIN
NS_BEGIN(Memory)
NS_PRIVATE_BEGIN
template <typename DestinationElementType, typename SourceElementType>
struct TCanBitwiseRelocate
{
enum
{
Value =
TypeTraits::TOr<
TypeTraits::TIsSame<DestinationElementType, SourceElementType>,
TypeTraits::TAnd<
TypeTraits::TIsBitwiseConstructible<DestinationElementType, SourceElementType>,
TypeTraits::TIsTriviallyDestructible<SourceElementType>
>
>::Value
};
};
NS_PRIVATE_END
template<typename ElementType, typename SizeType>
FORCEINLINE void DefaultConstructItems(void* Address, SizeType Count)
{
if constexpr (TypeTraits::TIsZeroConstructType<ElementType>::Value)
{
Memory::Memset(Address, 0, sizeof(ElementType) * Count);
}
else
{
ElementType* Element = (ElementType*)Address;
while (Count)
{
new (Element) ElementType;
++Element;
--Count;
}
}
}
template<typename ElementType, typename SizeType>
FORCEINLINE void DestructItems(ElementType* Element, SizeType Count)
{
if constexpr (!TypeTraits::TIsTriviallyDestructible<ElementType>::Value)
{
while (Count)
{
typedef ElementType DestructItemsElementTypeTypedef;
Element->DestructItemsElementTypeTypedef::~DestructItemsElementTypeTypedef();
++Element;
--Count;
}
}
}
template<typename DestinationElementType, typename SourceElementType, typename SizeType>
FORCEINLINE void ConstructItems(void* Dest, const SourceElementType* Source, SizeType Count)
{
if constexpr (TypeTraits::TIsBitwiseConstructible<DestinationElementType, SourceElementType>::Value)
{
Memory::Memcpy(Dest, Source, sizeof(SourceElementType) * Count);
}
else
{
while (Count)
{
new (Dest) DestinationElementType(*Source);
++(DestinationElementType*&)Dest;
++Source;
--Count;
}
}
}
template<typename ElementType, typename SizeType>
FORCEINLINE void CopyAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count)
{
if constexpr (TypeTraits::TIsTriviallyCopyAssignable<ElementType>::Value)
{
Memory::Memcpy(Dest, Source, sizeof(ElementType) * Count);
}
else
{
while (Count)
{
*Dest = *Source;
++Dest;
++Source;
--Count;
}
}
}
template<typename DestinationElementType, typename SourceElementType, typename SizeType>
FORCEINLINE void RelocateConstructItems(void* Dest, const SourceElementType* Source, SizeType Count)
{
if constexpr (NS_PRIVATE::TCanBitwiseRelocate<DestinationElementType, SourceElementType>::Value)
{
Memory::Memmove(Dest, Source, sizeof(SourceElementType) * Count);
}
else
{
while (Count)
{
typedef SourceElementType RelocateConstructItemsElementTypeTypedef;
new (Dest) DestinationElementType(*Source);
++(DestinationElementType*&)Dest;
(Source++)->RelocateConstructItemsElementTypeTypedef::~RelocateConstructItemsElementTypeTypedef();
--Count;
}
}
}
template<typename ElementType, typename SizeType>
FORCEINLINE void MoveConstructItems(void* Dest, const ElementType* Source, SizeType Count)
{
if constexpr (TypeTraits::TIsTriviallyCopyConstructible<ElementType>::Value)
{
Memory::Memmove(Dest, Source, sizeof(ElementType) * Count);
}
else
{
while (Count)
{
new (Dest) ElementType((ElementType&&)*Source);
++(ElementType*&)Dest;
++Source;
--Count;
}
}
}
template<typename ElementType, typename SizeType>
FORCEINLINE void MoveAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count)
{
if constexpr (TypeTraits::TIsTriviallyCopyAssignable<ElementType>::Value)
{
Memory::Memmove(Dest, Source, sizeof(ElementType) * Count);
}
else
{
while (Count)
{
*Dest = (ElementType&&)*Source;
++Dest;
++Source;
--Count;
}
}
}
template<typename ElementType, typename SizeType>
FORCEINLINE bool CompareItems(const ElementType* A, const ElementType* B, SizeType Count)
{
if constexpr (TypeTraits::TCanBitwiseCompare<ElementType>::Value)
{
return !Memory::Memcmp(A, B, sizeof(ElementType) * Count);
}
else
{
while (Count)
{
if (!(*A == *B))
{
return false;
}
++A;
++B;
--Count;
}
return true;
}
}
NS_END(Memory)
NS_REDCRAFT_END

View File

@ -7,7 +7,7 @@
NS_REDCRAFT_BEGIN
NS_BEGIN(TypeTraits)
// Primary type categories
// Primary type categories.
template <typename T> struct TIsVoid { static constexpr bool Value = std::is_void_v<T>; };
template <typename T> struct TIsNullPointer { static constexpr bool Value = std::is_null_pointer_v<T>; };
@ -24,7 +24,7 @@ template <typename T> struct TIsRValueReference { static constexpr bool Value
template <typename T> struct TIsMemberObjectPointer { static constexpr bool Value = std::is_member_object_pointer_v<T>; };
template <typename T> struct TIsMemberFunctionPointer { static constexpr bool Value = std::is_member_function_pointer_v<T>; };
// Composite type categories
// Composite type categories.
template <typename T> struct TIsFundamental { static constexpr bool Value = std::is_fundamental_v<T>; };
template <typename T> struct TIsArithmetic { static constexpr bool Value = std::is_arithmetic_v<T>; };
@ -34,7 +34,7 @@ template <typename T> struct TIsCompound { static constexpr bool Value = st
template <typename T> struct TIsReference { static constexpr bool Value = std::is_reference_v<T>; };
template <typename T> struct TIsMemberPointer { static constexpr bool Value = std::is_member_pointer_v<T>; };
// Type properties
// Type properties.
template <typename T> struct TIsConst { static constexpr bool Value = std::is_const_v<T>; };
template <typename T> struct TIsVolatile { static constexpr bool Value = std::is_volatile_v<T>; };
@ -52,7 +52,7 @@ template <typename T> struct TIsUnsigned { static constexpr
template <typename T> struct TIsBoundedArray { static constexpr bool Value = std::is_bounded_array_v<T>; };
template <typename T> struct TIsUnboundedArray { static constexpr bool Value = std::is_unbounded_array_v<T>; };
// Supported operations
// Supported operations.
template <typename T> struct TIsConstructible { static constexpr bool Value = std::is_constructible_v<T>; };
template <typename T> struct TIsTriviallyConstructible { static constexpr bool Value = std::is_trivially_constructible_v<T>; };
@ -74,12 +74,12 @@ template <typename T> struct THasVirtualDestructor { static constexpr bool V
template <typename T> struct TIsSwappableWith { static constexpr bool Value = std::is_swappable_with_v<T>; };
template <typename T> struct TIsSwappable { static constexpr bool Value = std::is_swappable_v<T>; };
// Property queries
// Property queries.
template <typename T> struct TRank { static constexpr size_t Value = std::rank_v<T>; };
template <typename T, size_t N = 0> struct TExtent { static constexpr size_t Value = std::extent_v<T, N>; };
// Type relationships
// Type relationships.
template <typename T, typename U> struct TIsSame { static constexpr bool Value = std::is_same_v<T, U>; };
template <typename T, typename U> struct TIsBaseOf { static constexpr bool Value = std::is_base_of_v<T, U>; };
@ -87,7 +87,7 @@ template <typename T, typename U> struct TIsConver
template <typename Func, typename... ArgTypes> struct TIsInvocable { static constexpr bool Value = std::is_invocable_v<Func, ArgTypes...>; };
template <typename Result, typename Func, typename... ArgTypes> struct TIsInvocableResult { static constexpr bool Value = std::is_invocable_r_v<Result, Func, ArgTypes...>; };
// Const-volatility specifiers
// Const-volatility specifiers.
template <typename T> struct TRemoveCV { typedef typename std::remove_cv_t<T> Type; };
template <typename T> struct TRemoveConst { typedef typename std::remove_const<T> Type; };
@ -96,28 +96,28 @@ template <typename T> struct TAddCV { typedef typename std::add_cv<T>
template <typename T> struct TAddConst { typedef typename std::add_const<T> Type; };
template <typename T> struct TAddVolatile { typedef typename std::add_volatile<T> Type; };
// References
// References.
template <typename T> struct TRemoveReference { typedef typename std::remove_reference_t<T> Type; };
template <typename T> struct TAddLValueReference { typedef typename std::add_lvalue_reference_t<T> Type; };
template <typename T> struct TAddRValueReference { typedef typename std::add_rvalue_reference_t<T> Type; };
// Pointers
// Pointers.
template <typename T> struct TRemovePointer { typedef typename std::remove_pointer_t<T> Type; };
template <typename T> struct TAddPointer { typedef typename std::add_pointer_t<T> Type; };
// Sign modifiers
// Sign modifiers.
template <typename T> struct TMakeSigned { typedef typename std::make_signed_t<T> Type; };
template <typename T> struct TMakeUnsigned { typedef typename std::make_unsigned_t<T> Type; };
// Arrays
// Arrays.
template <typename T> struct TRemoveExtent { typedef typename std::remove_extent_t<T> Type; };
template <typename T> struct TRemoveAllExtents { typedef typename std::remove_all_extents_t<T> Type; };
// Miscellaneous transformations
// Miscellaneous transformations.
template <size_t Len, size_t Alignment> struct TAlignedStorage { typedef typename std::aligned_storage_t<Len, Alignment> Type; };
template <size_t Len, typename... Types> struct TAlignedUnion { typedef typename std::aligned_union_t<Len, Types...> Type; };
@ -128,22 +128,75 @@ template <typename... T> struct TCommonType { typedef
template <typename T> struct TUnderlyingType { typedef typename std::underlying_type_t<T> Type; };
template <typename Func, typename... ArgTypes> struct TInvokeResult { typedef typename std::invoke_result_t<Func, ArgTypes...> Type; };
// Operations on traits
// Operations on traits.
template <typename T, T InValue> struct TConstant { static constexpr T Value = InValue; };
template <bool InValue> struct TBoolConstant : TConstant<bool, InValue> { };
template <typename T, T InValue> struct TConstant { static constexpr T Value = InValue; };
template <bool InValue> struct TBoolConstant : TConstant<bool, InValue> { };
template <typename... Types> struct TAnd;
template <typename... RHS> struct TAnd<TBoolConstant<true>, RHS...> { static constexpr bool Value = TAnd<RHS...>::Value; };
template <typename... RHS> struct TAnd<TBoolConstant<false>, RHS...> { static constexpr bool Value = false; };
template <> struct TAnd<> { static constexpr bool Value = true; };
template <typename... Types> struct TAnd;
template <typename LHS, typename... RHS> struct TAnd<LHS, RHS...> { static constexpr bool Value = LHS::Value && TAnd<RHS...>::Value; };
template <> struct TAnd<> { static constexpr bool Value = true; };
template <typename... Types> struct TOr;
template <typename... RHS> struct TOr<TBoolConstant<true>, RHS...> { static constexpr bool Value = true; };
template <typename... RHS> struct TOr<TBoolConstant<false>, RHS...> { static constexpr bool Value = TOr<RHS...>::Value; };
template <> struct TOr<> { static constexpr bool Value = false; };
template <typename... Types> struct TOr;
template <typename LHS, typename... RHS> struct TOr<LHS, RHS...> { static constexpr bool Value = LHS::Value || TOr<RHS...>::Value; };
template <> struct TOr<> { static constexpr bool Value = false; };
template <typename Type> struct TNot { static constexpr bool Value = !Type::Value; };
template <typename Type> struct TNot { static constexpr bool Value = !Type::Value; };
// Non-STD feature.
template <typename T>
struct TIsZeroConstructType
{
static constexpr bool Value = TOr<TIsEnum<T>, TIsArithmetic<T>, TIsPointer<T>>::Value;
};
template<typename T>
struct TCanBitwiseCompare
{
static constexpr bool Value = TOr<TIsEnum<T>, TIsArithmetic<T>, TIsPointer<T>>::Value;
};
template <typename T, typename U>
struct TIsBitwiseConstructible
{
static_assert(
!TIsReference<T>::Value &&
!TIsReference<U>::Value,
"TIsBitwiseConstructible is not designed to accept reference types");
static_assert(
TIsSame<T, typename TRemoveCV<T>::Type>::Value &&
TIsSame<U, typename TRemoveCV<U>::Type>::Value,
"TIsBitwiseConstructible is not designed to accept qualified types");
static constexpr bool Value = false;
};
template <typename T>
struct TIsBitwiseConstructible<T, T>
{
static constexpr bool Value = TIsTriviallyCopyConstructible<T>::Value;
};
template <typename T, typename U>
struct TIsBitwiseConstructible<const T, U> : TIsBitwiseConstructible<T, U>
{ };
template <typename T>
struct TIsBitwiseConstructible<const T*, T*>
{
static constexpr bool Value = true;
};
template <> struct TIsBitwiseConstructible< uint8, int8> { static constexpr bool Value = true; };
template <> struct TIsBitwiseConstructible< int8, uint8> { static constexpr bool Value = true; };
template <> struct TIsBitwiseConstructible<uint16, int16> { static constexpr bool Value = true; };
template <> struct TIsBitwiseConstructible< int16, uint16> { static constexpr bool Value = true; };
template <> struct TIsBitwiseConstructible<uint32, int32> { static constexpr bool Value = true; };
template <> struct TIsBitwiseConstructible< int32, uint32> { static constexpr bool Value = true; };
template <> struct TIsBitwiseConstructible<uint64, int64> { static constexpr bool Value = true; };
template <> struct TIsBitwiseConstructible< int64, uint64> { static constexpr bool Value = true; };
NS_END(TypeTraits)
NS_REDCRAFT_END

View File

@ -8,9 +8,52 @@
NS_STD_USING
NS_REDCRAFT_USING
struct FTest
{
FTest() { cout << "FTest()" << endl; }
~FTest() { cout << "~FTest()" << endl; }
FTest(int32) { cout << "FTest(int32)" << endl; }
FTest(const FTest&) { cout << "FTest(const FTest&)" << endl; }
FTest(FTest&&) { cout << "FTest(FTest&&)" << endl; }
FTest& operator =(const FTest&) { cout << "FTest& operator =(const FTest&)" << endl; return *this; }
FTest& operator =(FTest&&) { cout << "FTest& operator =(FTest&&)" << endl; return *this; }
friend bool operator ==(const FTest&, const FTest&) { cout << "bool operator ==(const FTest&, const FTest&)" << endl; return true; }
};
int main()
{
check_no_entry();
FTest* A = new FTest[2];
FTest* B = new FTest[2];
int32* C = new int32[2];
int32* D = new int32[2];
cout << " --- " << endl;
Memory::DefaultConstructItems<FTest>(A, 2);
Memory::DestructItems<FTest>(A, 2);
Memory::ConstructItems<FTest>(A, C, 2);
Memory::CopyAssignItems(B, A, 2);
Memory::RelocateConstructItems<FTest>(A, C, 2);
Memory::MoveConstructItems(B, A, 2);
Memory::MoveAssignItems(B, A, 2);
cout << (Memory::CompareItems(A, B, 2) ? "True" : "False") << endl;
Memory::DefaultConstructItems<int32>(C, 2);
Memory::DestructItems<int32>(C, 2);
Memory::ConstructItems<int32>(C, D, 2);
Memory::CopyAssignItems(D, C, 2);
Memory::RelocateConstructItems<int32>(D, C, 2);
Memory::MoveConstructItems(D, C, 2);
Memory::MoveAssignItems(D, C, 2);
cout << (Memory::CompareItems(C, D, 2) ? "True" : "False") << endl;
cout << " --- " << endl;
delete[] A;
delete[] B;
delete[] C;
delete[] D;
cout << "Done!" << endl;
return 0;
}