feat(templates): add TPropagateConst and the corresponding testing
This commit is contained in:
parent
e498d9b0b8
commit
2ef2c4a729
@ -25,6 +25,7 @@ void TestTemplates()
|
||||
TestFunction();
|
||||
TestAtomic();
|
||||
TestScopeHelper();
|
||||
TestPropagateConst();
|
||||
TestMiscTemplates();
|
||||
}
|
||||
|
||||
@ -1469,6 +1470,46 @@ void TestScopeHelper()
|
||||
|
||||
}
|
||||
|
||||
void TestPropagateConst()
|
||||
{
|
||||
{
|
||||
struct FTestA
|
||||
{
|
||||
void Check(bool bFlag) { check(!bFlag); }
|
||||
void Check(bool bFlag) const { check(bFlag); }
|
||||
};
|
||||
|
||||
struct FTestB
|
||||
{
|
||||
FTestB() { Ptr = &Object; }
|
||||
FTestA Object;
|
||||
TPropagateConst<FTestA*> Ptr;
|
||||
};
|
||||
|
||||
FTestB TempA;
|
||||
const FTestB TempB;
|
||||
|
||||
TempA.Ptr->Check(false);
|
||||
TempB.Ptr->Check(true);
|
||||
}
|
||||
|
||||
{
|
||||
int64 IntA;
|
||||
int64 IntB;
|
||||
|
||||
TPropagateConst<int64*> TempA;
|
||||
TPropagateConst<int64*> TempB = &IntA;
|
||||
TPropagateConst<int64*> TempC = &IntB;
|
||||
|
||||
TempA = TempB;
|
||||
TempB = TempC;
|
||||
|
||||
check(TempA.IsValid());
|
||||
check(TempA == &IntA);
|
||||
check(TempB == TempC);
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_UNNAMED_BEGIN
|
||||
|
||||
template <typename T>
|
||||
|
156
Redcraft.Utility/Source/Public/Templates/PropagateConst.h
Normal file
156
Redcraft.Utility/Source/Public/Templates/PropagateConst.h
Normal file
@ -0,0 +1,156 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Templates/Utility.h"
|
||||
#include "Templates/TypeHash.h"
|
||||
#include "Memory/PointerTraits.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
template <typename T> requires (TPointerTraits<T>::bIsPointer)
|
||||
class TPropagateConst;
|
||||
|
||||
NAMESPACE_PRIVATE_BEGIN
|
||||
|
||||
template <typename T> struct TIsTPropagateConst : FFalse { };
|
||||
template <typename T> struct TIsTPropagateConst<TPropagateConst<T>> : FTrue { };
|
||||
|
||||
NAMESPACE_PRIVATE_END
|
||||
|
||||
template <typename T>
|
||||
concept CTPropagateConst = NAMESPACE_PRIVATE::TIsTPropagateConst<TRemoveCV<T>>::Value;
|
||||
|
||||
/**
|
||||
* TPropagateConst is a const-propagating wrapper for pointers and pointer-like objects.
|
||||
* It treats the wrapped pointer as a pointer to const when accessed through a const access path, hence the name.
|
||||
*/
|
||||
template <typename T> requires (TPointerTraits<T>::bIsPointer)
|
||||
class TPropagateConst final
|
||||
{
|
||||
public:
|
||||
|
||||
using ElementType = TPointerTraits<T>::ElementType;
|
||||
|
||||
/** Constructs an TPropagateConst, default-initializing underlying pointer. */
|
||||
FORCEINLINE constexpr TPropagateConst() = default;
|
||||
|
||||
/** Initializes underlying pointer if by direct-non-list-initialization with the expression Forward<U>(InValue). */
|
||||
template <typename U> requires (CConstructibleFrom<T, U> && !CTPropagateConst<TRemoveCVRef<U>>)
|
||||
FORCEINLINE constexpr explicit (!CConvertibleTo<U, T>) TPropagateConst(U&& InValue)
|
||||
: Ptr(Forward<U>(InValue))
|
||||
{ }
|
||||
|
||||
/** Explicitly defaulted copy/move constructor that copy/move constructs underlying pointer. */
|
||||
FORCEINLINE constexpr TPropagateConst(const TPropagateConst&) = default;
|
||||
FORCEINLINE constexpr TPropagateConst(TPropagateConst&&) = default;
|
||||
|
||||
/** Initializes underlying pointer as if by direct-non-list-initialization. */
|
||||
template <typename U> requires (CConstructibleFrom<T, const U&>)
|
||||
FORCEINLINE constexpr explicit (!CConvertibleTo<const U&, T>) TPropagateConst(const TPropagateConst<U>& InValue)
|
||||
: Ptr(InValue.Ptr)
|
||||
{ }
|
||||
|
||||
/** Initializes underlying pointer as if by direct-non-list-initialization. */
|
||||
template <typename U> requires (CConstructibleFrom<T, U&&>)
|
||||
FORCEINLINE constexpr explicit (!CConvertibleTo<U&&, T>) TPropagateConst(TPropagateConst<U>&& InValue)
|
||||
: Ptr(MoveTemp(InValue.Ptr))
|
||||
{ }
|
||||
|
||||
/** Destructs an TPropagateConst, destroying the contained underlying pointer */
|
||||
FORCEINLINE constexpr ~TPropagateConst() = default;
|
||||
|
||||
/** Explicitly defaulted copy/move assignment operator that copy/move assigns underlying pointer. */
|
||||
FORCEINLINE constexpr TPropagateConst& operator=(const TPropagateConst& InValue) = default;
|
||||
FORCEINLINE constexpr TPropagateConst& operator=(TPropagateConst&& InValue) = default;
|
||||
|
||||
/** Assigns underlying pointer from 'InValue'. */
|
||||
template <typename U> requires (CAssignableFrom<T, const U&>)
|
||||
FORCEINLINE constexpr TPropagateConst& operator=(const TPropagateConst<T>& InValue)
|
||||
{
|
||||
Ptr = InValue.Ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Assigns underlying pointer from 'InValue'. */
|
||||
template <typename U> requires (CAssignableFrom<T, U&&>)
|
||||
FORCEINLINE constexpr TPropagateConst& operator=(TPropagateConst<T>&& InValue)
|
||||
{
|
||||
Ptr = MoveTemp(InValue.Ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Assigns underlying pointer from 'InValue'. */
|
||||
template <typename U> requires (CConvertibleTo<U, T>)
|
||||
FORCEINLINE constexpr TPropagateConst& operator=(U&& InValue)
|
||||
{
|
||||
Ptr = Forward<U>(InValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Compares the pointer values of two TPropagateConst. */
|
||||
NODISCARD friend FORCEINLINE constexpr bool operator==(const TPropagateConst& LHS, const TPropagateConst& RHS) requires (CWeaklyEqualityComparable<T>) { return LHS.Ptr == RHS.Ptr; }
|
||||
|
||||
/** Compares the pointer values of two TPropagateConst. */
|
||||
NODISCARD friend FORCEINLINE constexpr decltype(auto) operator<=>(const TPropagateConst& LHS, const TPropagateConst& RHS) requires (CSynthThreeWayComparable<T>) { return SynthThreeWayCompare(LHS.Ptr, RHS.Ptr); }
|
||||
|
||||
/** Compares the pointer values with a underlying pointer. */
|
||||
template <typename U> requires (CWeaklyEqualityComparable<T, U>)
|
||||
NODISCARD FORCEINLINE constexpr bool operator==(U InPtr) const& { return Ptr == InPtr; }
|
||||
|
||||
/** Compares the pointer values with a underlying pointer. */
|
||||
template <typename U> requires (CSynthThreeWayComparable<T, U>)
|
||||
NODISCARD FORCEINLINE constexpr decltype(auto) operator<=>(U InPtr) const& { return SynthThreeWayCompare(Ptr, InPtr); }
|
||||
|
||||
/** @return The pointer to the object pointed to by the wrapped pointer. */
|
||||
NODISCARD FORCEINLINE constexpr ElementType* Get() { return TPointerTraits<T>::ToAddress(Ptr); }
|
||||
NODISCARD FORCEINLINE constexpr const ElementType* Get() const { return TPointerTraits<T>::ToAddress(Ptr); }
|
||||
|
||||
/** @return true if *this owns an object, false otherwise. */
|
||||
NODISCARD FORCEINLINE constexpr bool IsValid() 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(). */
|
||||
NODISCARD FORCEINLINE constexpr ElementType& operator*() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); }
|
||||
NODISCARD FORCEINLINE constexpr const ElementType& operator*() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); }
|
||||
NODISCARD FORCEINLINE constexpr ElementType* operator->() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); }
|
||||
NODISCARD FORCEINLINE constexpr const ElementType* operator->() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); }
|
||||
|
||||
/** @return The element at index, i.e. Get()[Index]. */
|
||||
NODISCARD FORCEINLINE constexpr T& operator[](size_t Index) { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get()[Index]; }
|
||||
NODISCARD FORCEINLINE constexpr const T& operator[](size_t Index) const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get()[Index]; }
|
||||
|
||||
/** @return The pointer to the object pointed to by the wrapped pointer-like object. */
|
||||
NODISCARD FORCEINLINE constexpr operator ElementType*() requires (CConvertibleTo<T, ElementType*>) { return Ptr; }
|
||||
NODISCARD FORCEINLINE constexpr operator const ElementType*() const requires (CConvertibleTo<T, ElementType*>) { return Ptr; }
|
||||
|
||||
/** @return The reference to the pointer-like object stored. */
|
||||
NODISCARD FORCEINLINE constexpr T& GetUnderlying() { return Ptr; }
|
||||
NODISCARD FORCEINLINE constexpr const T& GetUnderlying() const { return Ptr; }
|
||||
|
||||
/** Overloads the GetTypeHash algorithm for TPropagateConst. */
|
||||
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(const TPropagateConst& A) requires (CHashable<T>)
|
||||
{
|
||||
return GetTypeHash(A.Ptr);
|
||||
}
|
||||
|
||||
/** Overloads the Swap algorithm for TPropagateConst. */
|
||||
friend FORCEINLINE constexpr void Swap(TPropagateConst& A, TPropagateConst& B) requires (CSwappable<T>)
|
||||
{
|
||||
Swap(A.Ptr, B.Ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
T Ptr;
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
TPropagateConst(T) -> TPropagateConst<T>;
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
@ -15,3 +15,4 @@
|
||||
#include "Templates/Function.h"
|
||||
#include "Templates/Atomic.h"
|
||||
#include "Templates/ScopeHelper.h"
|
||||
#include "Templates/PropagateConst.h"
|
||||
|
@ -18,6 +18,7 @@ REDCRAFTUTILITY_API void TestTuple();
|
||||
REDCRAFTUTILITY_API void TestFunction();
|
||||
REDCRAFTUTILITY_API void TestAtomic();
|
||||
REDCRAFTUTILITY_API void TestScopeHelper();
|
||||
REDCRAFTUTILITY_API void TestPropagateConst();
|
||||
REDCRAFTUTILITY_API void TestMiscTemplates();
|
||||
|
||||
NAMESPACE_END(Testing)
|
||||
|
Loading…
Reference in New Issue
Block a user