Compare commits

...

2 Commits

57 changed files with 1877 additions and 1705 deletions

View File

@ -46,7 +46,7 @@ public:
};
FMemoryLeakChecker MemoryLeakChecker;
FMemoryLeakChecker GMemoryLeakChecker;
#endif
@ -80,7 +80,7 @@ void* Malloc(size_t Count, size_t Alignment)
check(Result != nullptr);
check_code({ MemoryLeakChecker.AddMemoryAllocationCount(); });
check_code({ GMemoryLeakChecker.AddMemoryAllocationCount(); });
return Result;
}
@ -139,7 +139,7 @@ void Free(void* Ptr)
}
# endif
check_code({ MemoryLeakChecker.ReleaseMemoryAllocationCount(); });
check_code({ GMemoryLeakChecker.ReleaseMemoryAllocationCount(); });
}
size_t QuantizeSize(size_t Count, size_t Alignment)

View File

@ -10,15 +10,15 @@ NAMESPACE_BEGIN(Math)
NAMESPACE_UNNAMED_BEGIN
TAtomic<uint32> RandState = 586103306;
TAtomic<uint32> GRandState = 586103306;
NAMESPACE_UNNAMED_END
uint32 Seed(uint32 InSeed)
{
uint32 OldSeed = RandState.Load(EMemoryOrder::Relaxed);
uint32 OldSeed = GRandState.Load(EMemoryOrder::Relaxed);
if (InSeed != 0) RandState.Store(InSeed, EMemoryOrder::Relaxed);
if (InSeed != 0) GRandState.Store(InSeed, EMemoryOrder::Relaxed);
return OldSeed;
}
@ -27,7 +27,7 @@ uint32 Rand()
{
uint32 Result;
RandState.FetchFn(
GRandState.FetchFn(
[&Result](uint32 Value)
{
Result = Value;

View File

@ -7,6 +7,8 @@ NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
// ReSharper disable CppInconsistentNaming
NAMESPACE_BEGIN(Testing)
void TestContainers()
@ -603,6 +605,8 @@ void TestList()
NAMESPACE_END(Testing)
// ReSharper restore CppInconsistentNaming
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -255,23 +255,23 @@ void TestPointerTraits()
always_check(!TPointerTraits<int64>::bIsPointer);
always_check(TPointerTraits<int64*>::bIsPointer);
always_check((CSameAs<TPointerTraits<int64*>::PointerType, int64*>));
always_check((CSameAs<TPointerTraits<int64*>::ElementType, int64>));
always_check((CSameAs<TPointerTraits<int64*>::FPointerType, int64*>));
always_check((CSameAs<TPointerTraits<int64*>::FElementType, int64>));
always_check(TPointerTraits<int64*>::ToAddress(nullptr) == nullptr);
always_check(TPointerTraits<int64(*)[]>::bIsPointer);
always_check((CSameAs<TPointerTraits<int64(*)[]>::PointerType, int64(*)[]>));
always_check((CSameAs<TPointerTraits<int64(*)[]>::ElementType, int64>));
always_check((CSameAs<TPointerTraits<int64(*)[]>::FPointerType, int64(*)[]>));
always_check((CSameAs<TPointerTraits<int64(*)[]>::FElementType, int64>));
always_check(TPointerTraits<int64*>::ToAddress(nullptr) == nullptr);
always_check(TPointerTraits<TSharedPtr<int64>>::bIsPointer);
always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::PointerType, TSharedPtr<int64>>));
always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::ElementType, int64>));
always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::FPointerType, TSharedPtr<int64>>));
always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::FElementType, int64>));
always_check(TPointerTraits<TSharedPtr<int64>>::ToAddress(nullptr) == nullptr);
always_check(TPointerTraits<TSharedPtr<int64[]>>::bIsPointer);
always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::PointerType, TSharedPtr<int64[]>>));
always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::ElementType, int64>));
always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::FPointerType, TSharedPtr<int64[]>>));
always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::FElementType, int64>));
always_check(TPointerTraits<TSharedPtr<int64[]>>::ToAddress(nullptr) == nullptr);
}

View File

@ -64,9 +64,9 @@ void TestInvoke()
void TestReferenceWrapper()
{
typedef int32(*FuncType)(int32, int32, int32);
FuncType TempA = [](int32 A, int32 B, int32 C) -> int32 { return A * B * C; };
TReferenceWrapper<FuncType> TempB(TempA);
typedef int32(*FFuncType)(int32, int32, int32);
FFuncType TempA = [](int32 A, int32 B, int32 C) -> int32 { return A * B * C; };
TReferenceWrapper<FFuncType> TempB(TempA);
always_check(TempB(1, 1, 1) == 1);
TempB.Get() = &TestFunctionA;
always_check(TempA(1, 1, 1) == 3);
@ -330,14 +330,15 @@ void TestVariant()
}
{
using VariantType = TVariant<int32, int64, float64>;
VariantType TempArray[] = { 10, 15ll, 1.5 };
using FVariantType = TVariant<int32, int64, float64>;
FVariantType TempArray[] = { 10, 15ll, 1.5 };
for(auto&& TempA : TempArray)
{
Visit(
[](auto&& A)
{
// ReSharper disable once CppInconsistentNaming
using T = TRemoveCVRef<decltype(A)>;
if constexpr (CSameAs<T, int32>) always_check(A == 10);
else if constexpr (CSameAs<T, int64>) always_check(A == 15ll);
@ -347,11 +348,12 @@ void TestVariant()
TempA
);
VariantType TempB = Visit([](auto&& A) -> VariantType { return A + A; }, TempA);
FVariantType TempB = Visit([](auto&& A) -> FVariantType { return A + A; }, TempA);
Visit(
[](auto&& A, auto&& B)
{
// ReSharper disable once CppInconsistentNaming
using T = TRemoveCVRef<decltype(A)>;
if constexpr (CSameAs<T, int32>) always_check(A == 10 && B == 20);
else if constexpr (CSameAs<T, int64>) always_check(A == 15ll && B == 30ll);
@ -366,6 +368,7 @@ void TestVariant()
Visit(
[](auto&& A)
{
// ReSharper disable once CppInconsistentNaming
using T = TRemoveCVRef<decltype(A)>;
if constexpr (CSameAs<T, int32>) always_check(A == 20);
else if constexpr (CSameAs<T, int64>) always_check(A == 30ll);
@ -417,6 +420,7 @@ void TestVariant()
auto TestQualifiers = [&bIsConst, &bIsLValue, &bIsRValue](auto&& A) -> int32
{
// ReSharper disable once CppInconsistentNaming
using T = decltype(A);
always_check(A == 10);
always_check(CConst<TRemoveReference<T>> == bIsConst);
@ -429,6 +433,8 @@ void TestVariant()
bIsLValue = true;
bIsRValue = false;
// ReSharper disable CppInconsistentNaming
TVariant<int32> TempLA = 10;
auto ReturnLA = Visit(TestQualifiers, TempLA);
always_check((CSameAs<int32, decltype(ReturnLA)>));
@ -488,6 +494,8 @@ void TestVariant()
const TVariant<int32> TempRD = TempLC;
auto ReturnRD = Visit<int32>(TestQualifiers, MoveTemp(TempRD));
always_check((CSameAs<int32, decltype(ReturnRD)>));
// ReSharper restore CppInconsistentNaming
}
{
@ -869,11 +877,11 @@ void TestTuple()
// always_check((CSameAs<TTupleElement<4, TTuple<double, float&, char&&>>, double>));
{
using Type = TTuple<int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64,
using FType = TTuple<int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64,
int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64,
int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64>;
Type Temp;
FType Temp;
Temp.First = 0;
Temp.Second = 0;
@ -892,20 +900,20 @@ void TestTuple()
Temp.Fifteenth = 0;
Temp.Sixteenth = 0;
always_check(CDefaultConstructible<Type>);
always_check(CTriviallyDefaultConstructible<Type>);
always_check(CConstructibleFrom<Type>);
always_check(CTriviallyConstructibleFrom<Type>);
always_check(CCopyConstructible<Type>);
always_check(CTriviallyCopyConstructible<Type>);
always_check(CMoveConstructible<Type>);
always_check(CTriviallyMoveConstructible<Type>);
always_check(CCopyAssignable<Type>);
always_check(CTriviallyCopyAssignable<Type>);
always_check(CMoveAssignable<Type>);
always_check(CTriviallyMoveAssignable<Type>);
always_check(CDestructible<Type>);
always_check(CTriviallyDestructible<Type>);
always_check(CDefaultConstructible<FType>);
always_check(CTriviallyDefaultConstructible<FType>);
always_check(CConstructibleFrom<FType>);
always_check(CTriviallyConstructibleFrom<FType>);
always_check(CCopyConstructible<FType>);
always_check(CTriviallyCopyConstructible<FType>);
always_check(CMoveConstructible<FType>);
always_check(CTriviallyMoveConstructible<FType>);
always_check(CCopyAssignable<FType>);
always_check(CTriviallyCopyAssignable<FType>);
always_check(CMoveAssignable<FType>);
always_check(CTriviallyMoveAssignable<FType>);
always_check(CDestructible<FType>);
always_check(CTriviallyDestructible<FType>);
}
{
@ -1084,25 +1092,25 @@ struct FFunctionDebug
void Print(int32 In) { Output[Index++] = In; }
};
FFunctionDebug FunctionDebug;
FFunctionDebug GFunctionDebug;
struct FPrintAdd
{
FPrintAdd(int32 InNum) : Num(InNum) { }
void F(int32 I) const { FunctionDebug.Print(Num + I); }
void F(int32 I) const { GFunctionDebug.Print(Num + I); }
int32 Num;
};
void PrintNum(int32 I)
{
FunctionDebug.Print(I);
GFunctionDebug.Print(I);
}
struct FPrintNum
{
void operator()(int32 I) const
{
FunctionDebug.Print(I);
GFunctionDebug.Print(I);
}
};
@ -1310,7 +1318,7 @@ void TestFunction()
AddDisplay(314159, 1);
TFunction<int32(FPrintAdd const&)> Num = &FPrintAdd::Num;
FunctionDebug.Print(Num(Foo));
GFunctionDebug.Print(Num(Foo));
TFunction<void(int32)> AddDisplay2 = [Foo](int32 A) { Foo.F(A); };
AddDisplay2(2);
@ -1326,21 +1334,21 @@ void TestFunction()
return Fac(N);
};
for (int32 I = 5; I < 8; ++I) FunctionDebug.Print(Factorial(I));
for (int32 I = 5; I < 8; ++I) GFunctionDebug.Print(Factorial(I));
always_check(FunctionDebug.Index == 12);
always_check(FunctionDebug.Output[0] == -9);
always_check(FunctionDebug.Output[1] == 42);
always_check(FunctionDebug.Output[2] == 31337);
always_check(FunctionDebug.Output[3] == 314160);
always_check(FunctionDebug.Output[4] == 314160);
always_check(FunctionDebug.Output[5] == 314159);
always_check(FunctionDebug.Output[6] == 314161);
always_check(FunctionDebug.Output[7] == 314162);
always_check(FunctionDebug.Output[8] == 18);
always_check(FunctionDebug.Output[9] == 120);
always_check(FunctionDebug.Output[10] == 720);
always_check(FunctionDebug.Output[11] == 5040);
always_check(GFunctionDebug.Index == 12);
always_check(GFunctionDebug.Output[0] == -9);
always_check(GFunctionDebug.Output[1] == 42);
always_check(GFunctionDebug.Output[2] == 31337);
always_check(GFunctionDebug.Output[3] == 314160);
always_check(GFunctionDebug.Output[4] == 314160);
always_check(GFunctionDebug.Output[5] == 314159);
always_check(GFunctionDebug.Output[6] == 314161);
always_check(GFunctionDebug.Output[7] == 314162);
always_check(GFunctionDebug.Output[8] == 18);
always_check(GFunctionDebug.Output[9] == 120);
always_check(GFunctionDebug.Output[10] == 720);
always_check(GFunctionDebug.Output[11] == 5040);
}
{

View File

@ -14,7 +14,7 @@ NAMESPACE_BEGIN(Testing)
NAMESPACE_UNNAMED_BEGIN
int32 TestObject;
int32 GTestObject;
void TestFunction() { }
struct FTestStructA { };
@ -89,7 +89,7 @@ void TestTypeTraits()
always_check(!CLValueReference<int32>);
always_check(CLValueReference<int32&>);
always_check(!CLValueReference<int32&&>);
always_check(!CRValueReference<int32>);
always_check(!CRValueReference<int32&>);
always_check(CRValueReference<int32&&>);
@ -428,9 +428,9 @@ void TestTypeTraits()
always_check((CSameAs<void, TVoid<int32>>));
always_check((CSameAs<void, TVoid<int32, int64>>));
// Invocable.h
always_check((CInvocable<int32()>));
always_check((CInvocable<int32(int32), int32>));
always_check(!(CInvocable<int32(int32), FTestStructA>));
@ -462,7 +462,7 @@ void TestTypeTraits()
always_check((CSameAs<int32, TCommonReference<int8, int32>>));
always_check((CSameAs<int64, TCommonReference<int8, int32, int64>>));
always_check((CSameAs<double, TCommonReference<float, double>>));
always_check((CCommonType<int32, int32>));
always_check((CCommonType<int8, int32>));
always_check((CCommonType<float, double>));
@ -493,7 +493,7 @@ void TestTypeTraits()
always_check((CSameAs<const volatile int32, TCopyConst< int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyConst<const int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyConst<const volatile int32, const volatile int32>>));
always_check((CSameAs< int32, TCopyVolatile< int32, int32>>));
always_check((CSameAs< int32, TCopyVolatile<const int32, int32>>));
always_check((CSameAs< volatile int32, TCopyVolatile<const volatile int32, int32>>));
@ -503,7 +503,7 @@ void TestTypeTraits()
always_check((CSameAs<const volatile int32, TCopyVolatile< int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyVolatile<const int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyVolatile<const volatile int32, const volatile int32>>));
always_check((CSameAs< int32, TCopyCV< int32, int32>>));
always_check((CSameAs<const int32, TCopyCV<const int32, int32>>));
always_check((CSameAs<const volatile int32, TCopyCV<const volatile int32, int32>>));
@ -513,7 +513,7 @@ void TestTypeTraits()
always_check((CSameAs<const volatile int32, TCopyCV< int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyCV<const int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyCV<const volatile int32, const volatile int32>>));
always_check((CSameAs<int32, TCopyReference<int32, int32 >>));
always_check((CSameAs<int32&, TCopyReference<int32, int32& >>));
always_check((CSameAs<int32&&, TCopyReference<int32, int32&&>>));
@ -539,7 +539,7 @@ void TestTypeTraits()
always_check((CSameAs<const volatile int32, TCopyCVRef< int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyCVRef<const int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyCVRef<const volatile int32, const volatile int32>>));
always_check((CSameAs<int32, TCopyCVRef<int32, int32 >>));
always_check((CSameAs<int32&, TCopyCVRef<int32, int32& >>));
always_check((CSameAs<int32&&, TCopyCVRef<int32, int32&&>>));

View File

@ -27,41 +27,41 @@ private:
public:
using ElementType = T;
using AllocatorType = Allocator;
using FElementType = T;
using FAllocatorType = Allocator;
using Reference = T&;
using ConstReference = const T&;
using FReference = T&;
using FConstReference = const T&;
using Iterator = TIteratorImpl<false>;
using ConstIterator = TIteratorImpl<true >;
using FIterator = TIteratorImpl<false>;
using FConstIterator = TIteratorImpl<true >;
using ReverseIterator = TReverseIterator< Iterator>;
using ConstReverseIterator = TReverseIterator<ConstIterator>;
using FReverseIterator = TReverseIterator< FIterator>;
using FConstReverseIterator = TReverseIterator<FConstIterator>;
static_assert(CContiguousIterator< Iterator>);
static_assert(CContiguousIterator<ConstIterator>);
static_assert(CContiguousIterator< FIterator>);
static_assert(CContiguousIterator<FConstIterator>);
/** Default constructor. Constructs an empty container with a default-constructed allocator. */
FORCEINLINE TArray() : TArray(0) { }
/** Constructs the container with 'Count' default instances of T. */
explicit TArray(size_t Count) requires (CDefaultConstructible<ElementType>)
explicit TArray(size_t Count) requires (CDefaultConstructible<FElementType>)
{
Impl.ArrayNum = Count;
Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
Impl.Pointer = Impl->Allocate(Max());
Memory::DefaultConstruct<ElementType>(Impl.Pointer, Num());
Memory::DefaultConstruct<FElementType>(Impl.Pointer, Num());
}
/** Constructs the container with 'Count' copies of elements with 'InValue'. */
TArray(size_t Count, const ElementType& InValue) requires (CCopyConstructible<ElementType>)
TArray(size_t Count, const FElementType& InValue) requires (CCopyConstructible<FElementType>)
: TArray(MakeCountedConstantIterator(InValue, Count), DefaultSentinel)
{ }
/** Constructs the container with the contents of the range ['First', 'Last'). */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>> && CMovable<ElementType>)
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>> && CMovable<FElementType>)
TArray(I First, S Last)
{
if constexpr (CForwardIterator<I>)
@ -76,7 +76,7 @@ public:
for (size_t Index = 0; Index != Count; ++Index)
{
new (Impl.Pointer + Index) ElementType(*First++);
new (Impl.Pointer + Index) FElementType(*First++);
}
}
else
@ -94,17 +94,17 @@ public:
}
/** Copy constructor. Constructs the container with the copy of the contents of 'InValue'. */
TArray(const TArray& InValue) requires (CCopyConstructible<ElementType>)
TArray(const TArray& InValue) requires (CCopyConstructible<FElementType>)
{
Impl.ArrayNum = InValue.Num();
Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
Impl.Pointer = Impl->Allocate(Max());
Memory::CopyConstruct<ElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
Memory::CopyConstruct<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
}
/** Move constructor. After the move, 'InValue' is guaranteed to be empty. */
TArray(TArray&& InValue) requires (CMoveConstructible<ElementType>)
TArray(TArray&& InValue) requires (CMoveConstructible<FElementType>)
{
Impl.ArrayNum = InValue.Num();
@ -122,14 +122,14 @@ public:
Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
Memory::MoveConstruct<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
}
InValue.Reset();
}
/** Constructs the container with the contents of the initializer list. */
FORCEINLINE TArray(initializer_list<ElementType> IL) requires (CCopyConstructible<ElementType>) : TArray(Iteration::Begin(IL), Iteration::End(IL)) { }
FORCEINLINE TArray(initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) : TArray(Iteration::Begin(IL), Iteration::End(IL)) { }
/** Destructs the array. The destructors of the elements are called and the used storage is deallocated. */
~TArray()
@ -139,7 +139,7 @@ public:
}
/** Copy assignment operator. Replaces the contents with a copy of the contents of 'InValue'. */
TArray& operator=(const TArray& InValue) requires (CCopyable<ElementType>)
TArray& operator=(const TArray& InValue) requires (CCopyable<FElementType>)
{
if (&InValue == this) UNLIKELY return *this;
@ -157,7 +157,7 @@ public:
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::CopyConstruct<ElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
Memory::CopyConstruct<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
return *this;
}
@ -170,7 +170,7 @@ public:
else if (InValue.Num() <= Max())
{
Memory::CopyAssign(Impl.Pointer, InValue.Impl.Pointer, Num());
Memory::CopyConstruct<ElementType>(Impl.Pointer + Num(), InValue.Impl.Pointer + Num(), InValue.Num() - Num());
Memory::CopyConstruct<FElementType>(Impl.Pointer + Num(), InValue.Impl.Pointer + Num(), InValue.Num() - Num());
}
else check_no_entry();
@ -180,7 +180,7 @@ public:
}
/** Move assignment operator. After the move, 'InValue' is guaranteed to be empty. */
TArray& operator=(TArray&& InValue) requires (CMovable<ElementType>)
TArray& operator=(TArray&& InValue) requires (CMovable<FElementType>)
{
if (&InValue == this) UNLIKELY return *this;
@ -214,7 +214,7 @@ public:
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
Memory::MoveConstruct<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
InValue.Reset();
@ -229,7 +229,7 @@ public:
else if (InValue.Num() <= Max())
{
Memory::MoveAssign(Impl.Pointer, InValue.Impl.Pointer, Num());
Memory::MoveConstruct<ElementType>(Impl.Pointer + Num(), InValue.Impl.Pointer + Num(), InValue.Num() - Num());
Memory::MoveConstruct<FElementType>(Impl.Pointer + Num(), InValue.Impl.Pointer + Num(), InValue.Num() - Num());
}
else check_no_entry();
@ -241,7 +241,7 @@ public:
}
/** Replaces the contents with those identified by initializer list. */
TArray& operator=(initializer_list<ElementType> IL) requires (CCopyable<ElementType>)
TArray& operator=(initializer_list<FElementType> IL) requires (CCopyable<FElementType>)
{
size_t NumToAllocate = GetNum(IL);
@ -257,7 +257,7 @@ public:
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::CopyConstruct<ElementType>(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), Num());
Memory::CopyConstruct<FElementType>(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), Num());
return *this;
}
@ -270,7 +270,7 @@ public:
else if (GetNum(IL) <= Max())
{
Memory::CopyAssign(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), Num());
Memory::CopyConstruct<ElementType>(Impl.Pointer + Num(), NAMESPACE_REDCRAFT::GetData(IL) + Num(), GetNum(IL) - Num());
Memory::CopyConstruct<FElementType>(Impl.Pointer + Num(), NAMESPACE_REDCRAFT::GetData(IL) + Num(), GetNum(IL) - Num());
}
else check_no_entry();
@ -280,7 +280,7 @@ public:
}
/** Compares the contents of two arrays. */
NODISCARD friend bool operator==(const TArray& LHS, const TArray& RHS) requires (CWeaklyEqualityComparable<ElementType>)
NODISCARD friend bool operator==(const TArray& LHS, const TArray& RHS) requires (CWeaklyEqualityComparable<FElementType>)
{
if (LHS.Num() != RHS.Num()) return false;
@ -293,7 +293,7 @@ public:
}
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
NODISCARD friend auto operator<=>(const TArray& LHS, const TArray& RHS) requires (CSynthThreeWayComparable<ElementType>)
NODISCARD friend auto operator<=>(const TArray& LHS, const TArray& RHS) requires (CSynthThreeWayComparable<FElementType>)
{
const size_t NumToCompare = LHS.Num() < RHS.Num() ? LHS.Num() : RHS.Num();
@ -306,7 +306,7 @@ public:
}
/** Inserts 'InValue' before 'Iter' in the container. */
Iterator Insert(ConstIterator Iter, const ElementType& InValue) requires (CCopyable<ElementType>)
FIterator Insert(FConstIterator Iter, const FElementType& InValue) requires (CCopyable<FElementType>)
{
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
@ -318,26 +318,26 @@ public:
if (NumToAllocate != Max())
{
ElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() + 1;
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) ElementType(InValue);
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) FElementType(InValue);
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation);
return Iterator(this, Impl.Pointer + InsertIndex);
return FIterator(this, Impl.Pointer + InsertIndex);
}
if (InsertIndex != Num())
{
new (Impl.Pointer + Num()) ElementType(MoveTemp(Impl.Pointer[Num() - 1]));
new (Impl.Pointer + Num()) FElementType(MoveTemp(Impl.Pointer[Num() - 1]));
for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
{
@ -346,15 +346,15 @@ public:
Impl.Pointer[InsertIndex] = InValue;
}
else new (Impl.Pointer + Num()) ElementType(InValue);
else new (Impl.Pointer + Num()) FElementType(InValue);
Impl.ArrayNum = Num() + 1;
return Iterator(this, Impl.Pointer + InsertIndex);
return FIterator(this, Impl.Pointer + InsertIndex);
}
/** Inserts 'InValue' before 'Iter' in the container. */
Iterator Insert(ConstIterator Iter, ElementType&& InValue) requires (CMovable<ElementType>)
FIterator Insert(FConstIterator Iter, FElementType&& InValue) requires (CMovable<FElementType>)
{
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
@ -366,26 +366,26 @@ public:
if (NumToAllocate != Max())
{
ElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() + 1;
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) ElementType(MoveTemp(InValue));
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) FElementType(MoveTemp(InValue));
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation);
return Iterator(this, Impl.Pointer + InsertIndex);
return FIterator(this, Impl.Pointer + InsertIndex);
}
if (InsertIndex != Num())
{
new (Impl.Pointer + Num()) ElementType(MoveTemp(Impl.Pointer[Num() - 1]));
new (Impl.Pointer + Num()) FElementType(MoveTemp(Impl.Pointer[Num() - 1]));
for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
{
@ -394,15 +394,15 @@ public:
Impl.Pointer[InsertIndex] = MoveTemp(InValue);
}
else new (Impl.Pointer + Num()) ElementType(MoveTemp(InValue));
else new (Impl.Pointer + Num()) FElementType(MoveTemp(InValue));
Impl.ArrayNum = Num() + 1;
return Iterator(this, Impl.Pointer + InsertIndex);
return FIterator(this, Impl.Pointer + InsertIndex);
}
/** Inserts 'Count' copies of the 'InValue' before 'Iter' in the container. */
Iterator Insert(ConstIterator Iter, size_t Count, const ElementType& InValue) requires (CCopyable<ElementType>)
FIterator Insert(FConstIterator Iter, size_t Count, const FElementType& InValue) requires (CCopyable<FElementType>)
{
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
@ -410,9 +410,9 @@ public:
}
/** Inserts elements from range ['First', 'Last') before 'Iter'. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>
&& CAssignableFrom<ElementType&, TIteratorReferenceType<I>> && CMovable<ElementType>)
Iterator Insert(ConstIterator Iter, I First, S Last)
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>
&& CAssignableFrom<FElementType&, TIteratorReferenceType<I>> && CMovable<FElementType>)
FIterator Insert(FConstIterator Iter, I First, S Last)
{
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
@ -423,7 +423,7 @@ public:
const size_t InsertIndex = Iter - Begin();
const size_t Count = Iteration::Distance(First, Last);
if (Count == 0) return Iterator(this, Impl.Pointer + InsertIndex);
if (Count == 0) return FIterator(this, Impl.Pointer + InsertIndex);
const size_t NumToAllocate = Num() + Count > Max() ? Impl->CalculateSlackGrow(Num() + Count, Max()) : Max();
@ -431,26 +431,26 @@ public:
if (NumToAllocate != Max())
{
ElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() + Count;
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, InsertIndex);
for (size_t Index = InsertIndex; Index != InsertIndex + Count; ++Index)
{
new (Impl.Pointer + Index) ElementType(*First++);
new (Impl.Pointer + Index) FElementType(*First++);
}
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + Count, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + Count, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation);
return Iterator(this, Impl.Pointer + InsertIndex);
return FIterator(this, Impl.Pointer + InsertIndex);
}
/*
@ -492,7 +492,7 @@ public:
for (size_t TargetIndex = IndexO - 1; TargetIndex != IndexD - 1; --TargetIndex)
{
new (Impl.Pointer + TargetIndex) ElementType(MoveTemp(Impl.Pointer[TargetIndex - Count]));
new (Impl.Pointer + TargetIndex) FElementType(MoveTemp(Impl.Pointer[TargetIndex - Count]));
}
for (size_t TargetIndex = IndexD - 1; TargetIndex != IndexC - 1; --TargetIndex)
@ -507,14 +507,14 @@ public:
for (size_t TargetIndex = IndexB; TargetIndex != IndexC; ++TargetIndex)
{
new (Impl.Pointer + TargetIndex) ElementType(*First++);
new (Impl.Pointer + TargetIndex) FElementType(*First++);
}
check(First == Last);
Impl.ArrayNum = Num() + Count;
return Iterator(this, Impl.Pointer + InsertIndex);
return FIterator(this, Impl.Pointer + InsertIndex);
}
else
{
@ -524,14 +524,14 @@ public:
}
/** Inserts elements from initializer list before 'Iter' in the container. */
FORCEINLINE Iterator Insert(ConstIterator Iter, initializer_list<ElementType> IL) requires (CCopyable<ElementType>)
FORCEINLINE FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL) requires (CCopyable<FElementType>)
{
return Insert(Iter, Iteration::Begin(IL), Iteration::End(IL));
}
/** Inserts a new element into the container directly before 'Iter'. */
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...> && CMovable<ElementType>)
Iterator Emplace(ConstIterator Iter, Ts&&... Args)
template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...> && CMovable<FElementType>)
FIterator Emplace(FConstIterator Iter, Ts&&... Args)
{
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
@ -543,43 +543,43 @@ public:
if (NumToAllocate != Max())
{
ElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() + 1;
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) ElementType(Forward<Ts>(Args)...);
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) FElementType(Forward<Ts>(Args)...);
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation);
return Iterator(this, Impl.Pointer + InsertIndex);
return FIterator(this, Impl.Pointer + InsertIndex);
}
if (InsertIndex != Num())
{
new (Impl.Pointer + Num()) ElementType(MoveTemp(Impl.Pointer[Num() - 1]));
new (Impl.Pointer + Num()) FElementType(MoveTemp(Impl.Pointer[Num() - 1]));
for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
{
Impl.Pointer[Index] = MoveTemp(Impl.Pointer[Index - 1]);
}
Impl.Pointer[InsertIndex] = ElementType(Forward<Ts>(Args)...);
Impl.Pointer[InsertIndex] = FElementType(Forward<Ts>(Args)...);
}
else new (Impl.Pointer + Num()) ElementType(Forward<Ts>(Args)...);
else new (Impl.Pointer + Num()) FElementType(Forward<Ts>(Args)...);
Impl.ArrayNum = Num() + 1;
return Iterator(this, Impl.Pointer + InsertIndex);
return FIterator(this, Impl.Pointer + InsertIndex);
}
/** Removes the element at 'Iter' in the container. Without changing the order of elements. */
FORCEINLINE Iterator StableErase(ConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<ElementType>)
FORCEINLINE FIterator StableErase(FConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<FElementType>)
{
checkf(IsValidIterator(Iter) && Iter != End(), TEXT("Read access violation. Please check IsValidIterator()."));
@ -587,33 +587,33 @@ public:
}
/** Removes the elements in the range ['First', 'Last') in the container. Without changing the order of elements. */
Iterator StableErase(ConstIterator First, ConstIterator Last, bool bAllowShrinking = true) requires (CMovable<ElementType>)
FIterator StableErase(FConstIterator First, FConstIterator Last, bool bAllowShrinking = true) requires (CMovable<FElementType>)
{
checkf(IsValidIterator(First) && IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
const size_t EraseIndex = First - Begin();
const size_t EraseCount = Last - First;
if (EraseCount == 0) return Iterator(this, Impl.Pointer + EraseIndex);
if (EraseCount == 0) return FIterator(this, Impl.Pointer + EraseIndex);
const size_t NumToAllocate = bAllowShrinking ? Impl->CalculateSlackShrink(Num() - EraseCount, Max()) : Max();
if (NumToAllocate != Max())
{
ElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() - EraseCount;
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, EraseIndex);
Memory::MoveConstruct<ElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, EraseIndex);
Memory::MoveConstruct<FElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation);
return Iterator(this, Impl.Pointer + EraseIndex);
return FIterator(this, Impl.Pointer + EraseIndex);
}
for (size_t Index = EraseIndex + EraseCount; Index != Num(); ++Index)
@ -625,11 +625,11 @@ public:
Impl.ArrayNum = Num() - EraseCount;
return Iterator(this, Impl.Pointer + EraseIndex);
return FIterator(this, Impl.Pointer + EraseIndex);
}
/** Removes the element at 'Iter' in the container. But it may change the order of elements. */
FORCEINLINE Iterator Erase(ConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<ElementType>)
FORCEINLINE FIterator Erase(FConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<FElementType>)
{
checkf(IsValidIterator(Iter) && Iter != End(), TEXT("Read access violation. Please check IsValidIterator()."));
@ -637,33 +637,33 @@ public:
}
/** Removes the elements in the range ['First', 'Last') in the container. But it may change the order of elements. */
Iterator Erase(ConstIterator First, ConstIterator Last, bool bAllowShrinking = true) requires (CMovable<ElementType>)
FIterator Erase(FConstIterator First, FConstIterator Last, bool bAllowShrinking = true) requires (CMovable<FElementType>)
{
checkf(IsValidIterator(First) && IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
const size_t EraseIndex = First - Begin();
const size_t EraseCount = Last - First;
if (EraseCount == 0) return Iterator(this, Impl.Pointer + EraseIndex);
if (EraseCount == 0) return FIterator(this, Impl.Pointer + EraseIndex);
const size_t NumToAllocate = bAllowShrinking ? Impl->CalculateSlackShrink(Num() - EraseCount, Max()) : Max();
if (NumToAllocate != Max())
{
ElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() - EraseCount;
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, EraseIndex);
Memory::MoveConstruct<ElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, EraseIndex);
Memory::MoveConstruct<FElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation);
return Iterator(this, Impl.Pointer + EraseIndex);
return FIterator(this, Impl.Pointer + EraseIndex);
}
for (size_t Index = 0; Index != EraseCount; ++Index)
@ -677,24 +677,24 @@ public:
Impl.ArrayNum = Num() - EraseCount;
return Iterator(this, Impl.Pointer + EraseIndex);
return FIterator(this, Impl.Pointer + EraseIndex);
}
/** Appends the given element value to the end of the container. */
FORCEINLINE void PushBack(const ElementType& InValue) requires (CCopyable<ElementType>)
FORCEINLINE void PushBack(const FElementType& InValue) requires (CCopyable<FElementType>)
{
EmplaceBack(InValue);
}
/** Appends the given element value to the end of the container. */
FORCEINLINE void PushBack(ElementType&& InValue) requires (CMovable<ElementType>)
FORCEINLINE void PushBack(FElementType&& InValue) requires (CMovable<FElementType>)
{
EmplaceBack(MoveTemp(InValue));
}
/** Appends a new element to the end of the container. */
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...> && CMovable<ElementType>)
ElementType& EmplaceBack(Ts&&... Args)
template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...> && CMovable<FElementType>)
FElementType& EmplaceBack(Ts&&... Args)
{
const size_t NumToAllocate = Num() + 1 > Max() ? Impl->CalculateSlackGrow(Num() + 1, Max()) : Max();
@ -702,15 +702,15 @@ public:
if (NumToAllocate != Max())
{
ElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() + 1;
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num() - 1);
new (Impl.Pointer + Num() - 1) ElementType(Forward<Ts>(Args)...);
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num() - 1);
new (Impl.Pointer + Num() - 1) FElementType(Forward<Ts>(Args)...);
Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation);
@ -718,7 +718,7 @@ public:
return Impl.Pointer[Num() - 1];
}
new (Impl.Pointer + Num()) ElementType(Forward<Ts>(Args)...);
new (Impl.Pointer + Num()) FElementType(Forward<Ts>(Args)...);
Impl.ArrayNum = Num() + 1;
@ -726,13 +726,13 @@ public:
}
/** Removes the last element of the container. The array cannot be empty. */
FORCEINLINE void PopBack(bool bAllowShrinking = true) requires (CMovable<ElementType>)
FORCEINLINE void PopBack(bool bAllowShrinking = true) requires (CMovable<FElementType>)
{
Erase(End() - 1, bAllowShrinking);
}
/** Resizes the container to contain 'Count' elements. Additional default elements are appended. */
void SetNum(size_t Count, bool bAllowShrinking = true) requires (CDefaultConstructible<ElementType> && CMovable<ElementType>)
void SetNum(size_t Count, bool bAllowShrinking = true) requires (CDefaultConstructible<FElementType> && CMovable<FElementType>)
{
size_t NumToAllocate = Count;
@ -741,8 +741,8 @@ public:
if (NumToAllocate != Max())
{
ElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
Impl.ArrayNum = Count;
Impl.ArrayMax = NumToAllocate;
@ -750,12 +750,12 @@ public:
if (NumToDestruct <= Num())
{
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, NumToDestruct);
Memory::DefaultConstruct<ElementType>(Impl.Pointer + NumToDestruct, Num() - NumToDestruct);
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, NumToDestruct);
Memory::DefaultConstruct<FElementType>(Impl.Pointer + NumToDestruct, Num() - NumToDestruct);
}
else
{
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num());
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
}
Memory::Destruct(OldAllocation, NumToDestruct);
@ -770,7 +770,7 @@ public:
}
else if (Count <= Max())
{
Memory::DefaultConstruct<ElementType>(Impl.Pointer + Num(), Count - Num());
Memory::DefaultConstruct<FElementType>(Impl.Pointer + Num(), Count - Num());
}
else check_no_entry();
@ -778,7 +778,7 @@ public:
}
/** Resizes the container to contain 'Count' elements. Additional copies of 'InValue' are appended. */
void SetNum(size_t Count, const ElementType& InValue, bool bAllowShrinking = true) requires (CCopyConstructible<ElementType> && CMovable<ElementType>)
void SetNum(size_t Count, const FElementType& InValue, bool bAllowShrinking = true) requires (CCopyConstructible<FElementType> && CMovable<FElementType>)
{
size_t NumToAllocate = Count;
@ -787,8 +787,8 @@ public:
if (NumToAllocate != Max())
{
ElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num();
Impl.ArrayNum = Count;
Impl.ArrayMax = NumToAllocate;
@ -796,16 +796,16 @@ public:
if (NumToDestruct <= Num())
{
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, NumToDestruct);
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, NumToDestruct);
for (size_t Index = NumToDestruct; Index != Num(); ++Index)
{
new (Impl.Pointer + Index) ElementType(InValue);
new (Impl.Pointer + Index) FElementType(InValue);
}
}
else
{
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num());
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
}
Memory::Destruct(OldAllocation, NumToDestruct);
@ -822,7 +822,7 @@ public:
{
for (size_t Index = Num(); Index != Count; ++Index)
{
new (Impl.Pointer + Index) ElementType(InValue);
new (Impl.Pointer + Index) FElementType(InValue);
}
}
else check_no_entry();
@ -831,19 +831,19 @@ public:
}
/** Increase the max capacity of the array to a value that's greater or equal to 'Count'. */
void Reserve(size_t Count) requires (CMovable<ElementType>)
void Reserve(size_t Count) requires (CMovable<FElementType>)
{
if (Count <= Max()) return;
const size_t NumToAllocate = Impl->CalculateSlackReserve(Count);
ElementType* OldAllocation = Impl.Pointer;
const size_t NumToAllocate = Impl->CalculateSlackReserve(Count);
FElementType* OldAllocation = Impl.Pointer;
check(NumToAllocate > Max());
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num());
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
Memory::Destruct(OldAllocation, Num());
Impl->Deallocate(OldAllocation);
@ -858,32 +858,32 @@ public:
if (NumToAllocate == Max()) return;
ElementType* OldAllocation = Impl.Pointer;
FElementType* OldAllocation = Impl.Pointer;
Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num());
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
Memory::Destruct(OldAllocation, Num());
Impl->Deallocate(OldAllocation);
}
/** @return The pointer to the underlying element storage. */
NODISCARD FORCEINLINE ElementType* GetData() { return Impl.Pointer; }
NODISCARD FORCEINLINE const ElementType* GetData() const { return Impl.Pointer; }
NODISCARD FORCEINLINE FElementType* GetData() { return Impl.Pointer; }
NODISCARD FORCEINLINE const FElementType* GetData() const { return Impl.Pointer; }
/** @return The iterator to the first or end element. */
NODISCARD FORCEINLINE Iterator Begin() { return Iterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE ConstIterator Begin() const { return ConstIterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE Iterator End() { return Iterator(this, Impl.Pointer + Num()); }
NODISCARD FORCEINLINE ConstIterator End() const { return ConstIterator(this, Impl.Pointer + Num()); }
NODISCARD FORCEINLINE FIterator Begin() { return FIterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE FConstIterator Begin() const { return FConstIterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE FIterator End() { return FIterator(this, Impl.Pointer + Num()); }
NODISCARD FORCEINLINE FConstIterator End() const { return FConstIterator(this, Impl.Pointer + Num()); }
/** @return The reverse iterator to the first or end element. */
NODISCARD FORCEINLINE ReverseIterator RBegin() { return ReverseIterator(End()); }
NODISCARD FORCEINLINE ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
NODISCARD FORCEINLINE ReverseIterator REnd() { return ReverseIterator(Begin()); }
NODISCARD FORCEINLINE ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); }
NODISCARD FORCEINLINE FReverseIterator RBegin() { return FReverseIterator(End()); }
NODISCARD FORCEINLINE FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
NODISCARD FORCEINLINE FReverseIterator REnd() { return FReverseIterator(Begin()); }
NODISCARD FORCEINLINE FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
/** @return The number of elements in the container. */
NODISCARD FORCEINLINE size_t Num() const { return Impl.ArrayNum; }
@ -895,17 +895,17 @@ public:
NODISCARD FORCEINLINE bool IsEmpty() const { return Num() == 0; }
/** @return true if the iterator is valid, false otherwise. */
NODISCARD FORCEINLINE bool IsValidIterator(ConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
NODISCARD FORCEINLINE bool IsValidIterator(FConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
/** @return The reference to the requested element. */
NODISCARD FORCEINLINE ElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
NODISCARD FORCEINLINE const ElementType& operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
NODISCARD FORCEINLINE FElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
NODISCARD FORCEINLINE const FElementType& operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
/** @return The reference to the first or last element. */
NODISCARD FORCEINLINE ElementType& Front() { return *Begin(); }
NODISCARD FORCEINLINE const ElementType& Front() const { return *Begin(); }
NODISCARD FORCEINLINE ElementType& Back() { return *(End() - 1); }
NODISCARD FORCEINLINE const ElementType& Back() const { return *(End() - 1); }
NODISCARD FORCEINLINE FElementType& Front() { return *Begin(); }
NODISCARD FORCEINLINE const FElementType& Front() const { return *Begin(); }
NODISCARD FORCEINLINE FElementType& Back() { return *(End() - 1); }
NODISCARD FORCEINLINE const FElementType& Back() const { return *(End() - 1); }
/** Erases all elements from the container. After this call, Num() returns zero. */
void Reset(bool bAllowShrinking = true)
@ -929,11 +929,11 @@ public:
}
/** Overloads the GetTypeHash algorithm for TArray. */
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TArray& A) requires (CHashable<ElementType>)
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TArray& A) requires (CHashable<FElementType>)
{
size_t Result = 0;
for (ConstIterator Iter = A.Begin(); Iter != A.End(); ++Iter)
for (FConstIterator Iter = A.Begin(); Iter != A.End(); ++Iter)
{
Result = HashCombine(Result, GetTypeHash(*Iter));
}
@ -942,7 +942,7 @@ public:
}
/** Overloads the Swap algorithm for TArray. */
friend void Swap(TArray& A, TArray& B) requires (CMovable<ElementType>)
friend void Swap(TArray& A, TArray& B) requires (CMovable<FElementType>)
{
const bool bIsTransferable =
A.Impl->IsTransferable(A.Impl.Pointer) &&
@ -966,13 +966,13 @@ public:
private:
ALLOCATOR_WRAPPER_BEGIN(AllocatorType, ElementType, Impl)
ALLOCATOR_WRAPPER_BEGIN(FAllocatorType, FElementType, Impl)
{
size_t ArrayNum;
size_t ArrayMax;
ElementType* Pointer;
FElementType* Pointer;
}
ALLOCATOR_WRAPPER_END(AllocatorType, ElementType, Impl)
ALLOCATOR_WRAPPER_END(FAllocatorType, FElementType, Impl)
private:
@ -981,7 +981,7 @@ private:
{
public:
using ElementType = TRemoveCV<T>;
using FElementType = TRemoveCV<T>;
FORCEINLINE TIteratorImpl() = default;

View File

@ -29,15 +29,15 @@ class TArrayView
{
public:
using ElementType = T;
using FElementType = T;
using Reference = T&;
using FReference = T&;
class Iterator;
class FIterator;
using ReverseIterator = TReverseIterator<Iterator>;
using FReverseIterator = TReverseIterator<FIterator>;
static_assert(CContiguousIterator<Iterator>);
static_assert(CContiguousIterator<FIterator>);
static constexpr size_t Extent = InExtent;
@ -53,7 +53,7 @@ public:
}
/** Constructs an array view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */
template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], ElementType(*)[]>)
template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], FElementType(*)[]>)
FORCEINLINE constexpr explicit (Extent != DynamicExtent) TArrayView(I InFirst, size_t InCount)
{
checkf(Extent == DynamicExtent || Extent == InCount, TEXT("Illegal range count. Please check InCount."));
@ -67,7 +67,7 @@ public:
}
/** Constructs an array view that is a view over the range ['InFirst', 'InLast'). */
template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], ElementType(*)[]>)
template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], FElementType(*)[]>)
FORCEINLINE constexpr explicit (Extent != DynamicExtent) TArrayView(I InFirst, S InLast)
{
checkf(Extent == DynamicExtent || Extent == InLast - InFirst, TEXT("Illegal range iterator. Please check InLast - InFirst."));
@ -82,7 +82,7 @@ public:
/** Constructs an array view that is a view over the array 'InArray'. */
template <size_t N> requires (Extent == DynamicExtent || N == Extent)
FORCEINLINE constexpr TArrayView(ElementType(&InArray)[N])
FORCEINLINE constexpr TArrayView(FElementType(&InArray)[N])
{
Impl.Pointer = InArray;
@ -93,23 +93,23 @@ public:
}
/** Constructs an array view that is a view over the array 'InArray'. */
template <typename U, size_t N> requires (CConvertibleTo<U(*)[], ElementType(*)[]>)
template <typename U, size_t N> requires (CConvertibleTo<U(*)[], FElementType(*)[]>)
FORCEINLINE constexpr TArrayView(TStaticArray<U, N>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
/** Constructs an array view that is a view over the array 'InArray'. */
template <typename U, size_t N> requires (CConvertibleTo<const U(*)[], ElementType(*)[]>)
template <typename U, size_t N> requires (CConvertibleTo<const U(*)[], FElementType(*)[]>)
FORCEINLINE constexpr TArrayView(const TStaticArray<U, N>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
/** Constructs an array view that is a view over the array 'InArray'. */
template <typename U, typename Allocator> requires (CConvertibleTo<U(*)[], ElementType(*)[]>)
template <typename U, typename Allocator> requires (CConvertibleTo<U(*)[], FElementType(*)[]>)
FORCEINLINE constexpr TArrayView(TArray<U, Allocator>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
/** Constructs an array view that is a view over the array 'InArray'. */
template <typename U, typename Allocator> requires (CConvertibleTo<const U(*)[], ElementType(*)[]>)
template <typename U, typename Allocator> requires (CConvertibleTo<const U(*)[], FElementType(*)[]>)
FORCEINLINE constexpr TArrayView(const TArray<U, Allocator>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
/** Converting constructor from another array view 'InValue'. */
template <typename U, size_t N> requires ((Extent == DynamicExtent || N == DynamicExtent || N == Extent) && CConvertibleTo<U(*)[], ElementType(*)[]>)
template <typename U, size_t N> requires ((Extent == DynamicExtent || N == DynamicExtent || N == Extent) && CConvertibleTo<U(*)[], FElementType(*)[]>)
FORCEINLINE constexpr explicit (Extent != DynamicExtent && N == DynamicExtent) TArrayView(TArrayView<U, N> InValue)
{
checkf(Extent == DynamicExtent || Extent == InValue.Num(), TEXT("Illegal view extent. Please check InValue.Num()."));
@ -129,7 +129,7 @@ public:
FORCEINLINE constexpr TArrayView& operator=(const TArrayView&) noexcept = default;
/** Compares the contents of two array views. */
NODISCARD friend constexpr bool operator==(TArrayView LHS, TArrayView RHS) requires (CWeaklyEqualityComparable<ElementType>)
NODISCARD friend constexpr bool operator==(TArrayView LHS, TArrayView RHS) requires (CWeaklyEqualityComparable<FElementType>)
{
if (LHS.Num() != RHS.Num()) return false;
@ -142,7 +142,7 @@ public:
}
/** Compares the contents of two array views. */
NODISCARD friend constexpr auto operator<=>(TArrayView LHS, TArrayView RHS) requires (CSynthThreeWayComparable<ElementType>)
NODISCARD friend constexpr auto operator<=>(TArrayView LHS, TArrayView RHS) requires (CSynthThreeWayComparable<FElementType>)
{
const size_t NumToCompare = LHS.Num() < RHS.Num() ? LHS.Num() : RHS.Num();
@ -156,36 +156,36 @@ public:
/** Obtains an array view that is a view over the first 'Count' elements of this array view. */
template <size_t Count> requires (Extent == DynamicExtent || Extent >= Count)
NODISCARD FORCEINLINE constexpr TArrayView<ElementType, Count> First() const
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, Count> First() const
{
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
return TArrayView<ElementType, Count>(Begin(), Count);
return TArrayView<FElementType, Count>(Begin(), Count);
}
/** Obtains an array view that is a view over the first 'Count' elements of this array view. */
NODISCARD FORCEINLINE constexpr TArrayView<ElementType, DynamicExtent> First(size_t Count) const
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, DynamicExtent> First(size_t Count) const
{
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
return TArrayView<ElementType, DynamicExtent>(Begin(), Count);
return TArrayView<FElementType, DynamicExtent>(Begin(), Count);
}
/** Obtains an array view that is a view over the last 'Count' elements of this array view. */
template <size_t Count> requires (Extent == DynamicExtent || Extent >= Count)
NODISCARD FORCEINLINE constexpr TArrayView<ElementType, Count> Last() const
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, Count> Last() const
{
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
return TArrayView<ElementType, Count>(End() - Count, Count);
return TArrayView<FElementType, Count>(End() - Count, Count);
}
/** Obtains an array view that is a view over the last 'Count' elements of this array view. */
NODISCARD FORCEINLINE constexpr TArrayView<ElementType, DynamicExtent> Last(size_t Count) const
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, DynamicExtent> Last(size_t Count) const
{
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
return TArrayView<ElementType, DynamicExtent>(End() - Count, Count);
return TArrayView<FElementType, DynamicExtent>(End() - Count, Count);
}
/** Obtains an array view that is a view over the 'Count' elements of this array view starting at 'Offset'. */
@ -198,11 +198,11 @@ public:
if constexpr (Count != DynamicExtent)
{
return TArrayView<ElementType, SubviewExtent>(Begin() + Offset, Count);
return TArrayView<FElementType, SubviewExtent>(Begin() + Offset, Count);
}
else
{
return TArrayView<ElementType, SubviewExtent>(Begin() + Offset, Num() - Offset);
return TArrayView<FElementType, SubviewExtent>(Begin() + Offset, Num() - Offset);
}
}
@ -213,20 +213,20 @@ public:
if (Count != DynamicExtent)
{
return TArrayView<ElementType, DynamicExtent>(Begin() + Offset, Count);
return TArrayView<FElementType, DynamicExtent>(Begin() + Offset, Count);
}
else
{
return TArrayView<ElementType, DynamicExtent>(Begin() + Offset, Num() - Offset);
return TArrayView<FElementType, DynamicExtent>(Begin() + Offset, Num() - Offset);
}
}
/** Obtains an array view to the object representation of the elements of the array view. */
NODISCARD FORCEINLINE constexpr auto AsBytes()
{
constexpr size_t BytesExtent = Extent != DynamicExtent ? sizeof(ElementType) * Extent : DynamicExtent;
constexpr size_t BytesExtent = Extent != DynamicExtent ? sizeof(FElementType) * Extent : DynamicExtent;
if constexpr (!CConst<ElementType>)
if constexpr (!CConst<FElementType>)
{
return TArrayView<uint8, BytesExtent>(reinterpret_cast<uint8*>(GetData()), NumBytes());
}
@ -239,47 +239,47 @@ public:
/** Obtains an array view to the object representation of the elements of the array view. */
NODISCARD FORCEINLINE constexpr auto AsBytes() const
{
constexpr size_t BytesExtent = Extent != DynamicExtent ? sizeof(ElementType) * Extent : DynamicExtent;
constexpr size_t BytesExtent = Extent != DynamicExtent ? sizeof(FElementType) * Extent : DynamicExtent;
return TArrayView<const uint8, BytesExtent>(reinterpret_cast<const uint8*>(GetData()), NumBytes());
}
/** @return The pointer to the underlying element storage. */
NODISCARD FORCEINLINE constexpr ElementType* GetData() const { return Impl.Pointer; }
NODISCARD FORCEINLINE constexpr FElementType* GetData() const { return Impl.Pointer; }
/** @return The iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE constexpr Iterator End() const { return Iterator(this, Impl.Pointer + Num()); }
NODISCARD FORCEINLINE constexpr FIterator Begin() const { return FIterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE constexpr FIterator End() const { return FIterator(this, Impl.Pointer + Num()); }
/** @return The reverse iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() const { return ReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr ReverseIterator REnd() const { return ReverseIterator(Begin()); }
NODISCARD FORCEINLINE constexpr FReverseIterator RBegin() const { return FReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr FReverseIterator REnd() const { return FReverseIterator(Begin()); }
/** @return The number of elements in the container. */
NODISCARD FORCEINLINE constexpr size_t Num() const { if constexpr (Extent == DynamicExtent) { return Impl.ArrayNum; } return Extent; }
/** @return The number of bytes in the container. */
NODISCARD FORCEINLINE constexpr size_t NumBytes() const { return Num() * sizeof(ElementType); }
NODISCARD FORCEINLINE constexpr size_t NumBytes() const { return Num() * sizeof(FElementType); }
/** @return true if the container is empty, false otherwise. */
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; }
/** @return true if the iterator is valid, false otherwise. */
NODISCARD FORCEINLINE constexpr bool IsValidIterator(Iterator Iter) const { return Begin() <= Iter && Iter <= End(); }
NODISCARD FORCEINLINE constexpr bool IsValidIterator(FIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
/** @return The reference to the requested element. */
NODISCARD FORCEINLINE constexpr Reference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
NODISCARD FORCEINLINE constexpr FReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
/** @return The reference to the first or last element. */
NODISCARD FORCEINLINE constexpr Reference Front() const { return *Begin(); }
NODISCARD FORCEINLINE constexpr Reference Back() const { return *(End() - 1); }
NODISCARD FORCEINLINE constexpr FReference Front() const { return *Begin(); }
NODISCARD FORCEINLINE constexpr FReference Back() const { return *(End() - 1); }
/** Overloads the GetTypeHash algorithm for TArrayView. */
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(TArrayView A) requires (CHashable<ElementType>)
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(TArrayView A) requires (CHashable<FElementType>)
{
size_t Result = 0;
for (Iterator Iter = A.Begin(); Iter != A.End(); ++Iter)
for (FIterator Iter = A.Begin(); Iter != A.End(); ++Iter)
{
Result = HashCombine(Result, GetTypeHash(*Iter));
}
@ -291,7 +291,7 @@ public:
private:
struct FImplWithoutNum { ElementType* Pointer; };
struct FImplWithoutNum { FElementType* Pointer; };
struct FImplWithNum : FImplWithoutNum { size_t ArrayNum; };
@ -299,42 +299,42 @@ private:
public:
class Iterator final
class FIterator final
{
public:
using ElementType = TRemoveCV<T>;
using FElementType = TRemoveCV<T>;
FORCEINLINE constexpr Iterator() = default;
FORCEINLINE constexpr Iterator(const Iterator&) = default;
FORCEINLINE constexpr Iterator(Iterator&&) = default;
FORCEINLINE constexpr Iterator& operator=(const Iterator&) = default;
FORCEINLINE constexpr Iterator& operator=(Iterator&&) = default;
FORCEINLINE constexpr FIterator() = default;
FORCEINLINE constexpr FIterator(const FIterator&) = default;
FORCEINLINE constexpr FIterator(FIterator&&) = default;
FORCEINLINE constexpr FIterator& operator=(const FIterator&) = default;
FORCEINLINE constexpr FIterator& operator=(FIterator&&) = default;
NODISCARD friend FORCEINLINE constexpr bool operator==(const Iterator& LHS, const Iterator& RHS) { return LHS.Pointer == RHS.Pointer; }
NODISCARD friend FORCEINLINE constexpr bool operator==(const FIterator& LHS, const FIterator& RHS) { return LHS.Pointer == RHS.Pointer; }
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const Iterator& LHS, const Iterator& RHS) { return LHS.Pointer <=> RHS.Pointer; }
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const FIterator& LHS, const FIterator& RHS) { return LHS.Pointer <=> RHS.Pointer; }
NODISCARD FORCEINLINE constexpr T& operator*() const { CheckThis(true ); return *Pointer; }
NODISCARD FORCEINLINE constexpr T* operator->() const { CheckThis(false); return Pointer; }
NODISCARD FORCEINLINE constexpr T& operator[](ptrdiff Index) const { Iterator Temp = *this + Index; return *Temp; }
NODISCARD FORCEINLINE constexpr T& operator[](ptrdiff Index) const { FIterator Temp = *this + Index; return *Temp; }
FORCEINLINE constexpr Iterator& operator++() { ++Pointer; CheckThis(); return *this; }
FORCEINLINE constexpr Iterator& operator--() { --Pointer; CheckThis(); return *this; }
FORCEINLINE constexpr FIterator& operator++() { ++Pointer; CheckThis(); return *this; }
FORCEINLINE constexpr FIterator& operator--() { --Pointer; CheckThis(); return *this; }
FORCEINLINE constexpr Iterator operator++(int) { Iterator Temp = *this; ++*this; return Temp; }
FORCEINLINE constexpr Iterator operator--(int) { Iterator Temp = *this; --*this; return Temp; }
FORCEINLINE constexpr FIterator operator++(int) { FIterator Temp = *this; ++*this; return Temp; }
FORCEINLINE constexpr FIterator operator--(int) { FIterator Temp = *this; --*this; return Temp; }
FORCEINLINE constexpr Iterator& operator+=(ptrdiff Offset) { Pointer += Offset; CheckThis(); return *this; }
FORCEINLINE constexpr Iterator& operator-=(ptrdiff Offset) { Pointer -= Offset; CheckThis(); return *this; }
FORCEINLINE constexpr FIterator& operator+=(ptrdiff Offset) { Pointer += Offset; CheckThis(); return *this; }
FORCEINLINE constexpr FIterator& operator-=(ptrdiff Offset) { Pointer -= Offset; CheckThis(); return *this; }
NODISCARD friend FORCEINLINE constexpr Iterator operator+(Iterator Iter, ptrdiff Offset) { Iterator Temp = Iter; Temp += Offset; return Temp; }
NODISCARD friend FORCEINLINE constexpr Iterator operator+(ptrdiff Offset, Iterator Iter) { Iterator Temp = Iter; Temp += Offset; return Temp; }
NODISCARD friend FORCEINLINE constexpr FIterator operator+(FIterator Iter, ptrdiff Offset) { FIterator Temp = Iter; Temp += Offset; return Temp; }
NODISCARD friend FORCEINLINE constexpr FIterator operator+(ptrdiff Offset, FIterator Iter) { FIterator Temp = Iter; Temp += Offset; return Temp; }
NODISCARD FORCEINLINE constexpr Iterator operator-(ptrdiff Offset) const { Iterator Temp = *this; Temp -= Offset; return Temp; }
NODISCARD FORCEINLINE constexpr FIterator operator-(ptrdiff Offset) const { FIterator Temp = *this; Temp -= Offset; return Temp; }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const Iterator& LHS, const Iterator& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Pointer - RHS.Pointer; }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIterator& LHS, const FIterator& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Pointer - RHS.Pointer; }
private:
@ -345,11 +345,11 @@ public:
T* Pointer = nullptr;
# if DO_CHECK
FORCEINLINE constexpr Iterator(const TArrayView* InContainer, T* InPointer)
FORCEINLINE constexpr FIterator(const TArrayView* InContainer, T* InPointer)
: Owner(InContainer), Pointer(InPointer)
{ }
# else
FORCEINLINE constexpr Iterator(const TArrayView* InContainer, T* InPointer)
FORCEINLINE constexpr FIterator(const TArrayView* InContainer, T* InPointer)
: Pointer(InPointer)
{ }
# endif

View File

@ -30,23 +30,23 @@ private:
public:
using BlockType = InBlockType;
using ElementType = bool;
using AllocatorType = Allocator;
using FBlockType = InBlockType;
using FElementType = bool;
using FAllocatorType = Allocator;
class Reference;
using ConstReference = bool;
class FReference;
using FConstReference = bool;
using Iterator = TIteratorImpl<false>;
using ConstIterator = TIteratorImpl<true >;
using FIterator = TIteratorImpl<false>;
using FConstIterator = TIteratorImpl<true >;
using ReverseIterator = TReverseIterator< Iterator>;
using ConstReverseIterator = TReverseIterator<ConstIterator>;
using FReverseIterator = TReverseIterator< FIterator>;
using FConstReverseIterator = TReverseIterator<FConstIterator>;
static_assert(CRandomAccessIterator< Iterator>);
static_assert(CRandomAccessIterator<ConstIterator>);
static_assert(CRandomAccessIterator< FIterator>);
static_assert(CRandomAccessIterator<FConstIterator>);
static constexpr size_t BlockWidth = sizeof(BlockType) * 8;
static constexpr size_t BlockWidth = sizeof(FBlockType) * 8;
/** Default constructor. Constructs an empty bitset. */
FORCEINLINE TBitset() : TBitset(0) { }
@ -62,40 +62,40 @@ public:
/** Constructs a bitset from an integer. */
TBitset(size_t InCount, uint64 InValue) : TBitset(InCount > 64 ? InCount : 64)
{
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
if constexpr (sizeof(BlockType) == sizeof(uint8))
if constexpr (sizeof(FBlockType) == sizeof(uint8))
{
Impl.Pointer[0] = static_cast<BlockType>(InValue >> 0);
Impl.Pointer[1] = static_cast<BlockType>(InValue >> 8);
Impl.Pointer[2] = static_cast<BlockType>(InValue >> 16);
Impl.Pointer[3] = static_cast<BlockType>(InValue >> 24);
Impl.Pointer[4] = static_cast<BlockType>(InValue >> 32);
Impl.Pointer[5] = static_cast<BlockType>(InValue >> 40);
Impl.Pointer[6] = static_cast<BlockType>(InValue >> 48);
Impl.Pointer[7] = static_cast<BlockType>(InValue >> 56);
Impl.Pointer[0] = static_cast<FBlockType>(InValue >> 0);
Impl.Pointer[1] = static_cast<FBlockType>(InValue >> 8);
Impl.Pointer[2] = static_cast<FBlockType>(InValue >> 16);
Impl.Pointer[3] = static_cast<FBlockType>(InValue >> 24);
Impl.Pointer[4] = static_cast<FBlockType>(InValue >> 32);
Impl.Pointer[5] = static_cast<FBlockType>(InValue >> 40);
Impl.Pointer[6] = static_cast<FBlockType>(InValue >> 48);
Impl.Pointer[7] = static_cast<FBlockType>(InValue >> 56);
}
else if constexpr (sizeof(BlockType) == sizeof(uint16))
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
{
Impl.Pointer[0] = static_cast<BlockType>(InValue >> 0);
Impl.Pointer[1] = static_cast<BlockType>(InValue >> 16);
Impl.Pointer[2] = static_cast<BlockType>(InValue >> 32);
Impl.Pointer[3] = static_cast<BlockType>(InValue >> 48);
Impl.Pointer[0] = static_cast<FBlockType>(InValue >> 0);
Impl.Pointer[1] = static_cast<FBlockType>(InValue >> 16);
Impl.Pointer[2] = static_cast<FBlockType>(InValue >> 32);
Impl.Pointer[3] = static_cast<FBlockType>(InValue >> 48);
}
else if constexpr (sizeof(BlockType) == sizeof(uint32))
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
{
Impl.Pointer[0] = static_cast<BlockType>(InValue >> 0);
Impl.Pointer[1] = static_cast<BlockType>(InValue >> 32);
Impl.Pointer[0] = static_cast<FBlockType>(InValue >> 0);
Impl.Pointer[1] = static_cast<FBlockType>(InValue >> 32);
}
else if constexpr (sizeof(BlockType) == sizeof(uint64))
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
{
Impl.Pointer[0] = static_cast<BlockType>(InValue >> 0);
Impl.Pointer[0] = static_cast<FBlockType>(InValue >> 0);
}
else check_no_entry();
size_t BlockInteger = sizeof(uint64) / sizeof(BlockType);
size_t BlockInteger = sizeof(uint64) / sizeof(FBlockType);
Memory::Memset(Impl.Pointer + BlockInteger, 0, (NumBlocks() - BlockInteger) * sizeof(BlockType));
Memory::Memset(Impl.Pointer + BlockInteger, 0, (NumBlocks() - BlockInteger) * sizeof(FBlockType));
Impl.BitsetNum = InCount;
}
@ -112,9 +112,7 @@ public:
new (this) TBitset(InCount);
BlockType* CurrentBlock = Impl.Pointer - 1;
for (Reference Ref: *this) Ref = *First++;
for (FReference Ref: *this) Ref = *First++;
}
else
{
@ -135,7 +133,7 @@ public:
Impl.BlocksMax = Impl->CalculateSlackReserve(NumBlocks());
Impl.Pointer = Impl->Allocate(MaxBlocks());
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(BlockType));
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(FBlockType));
}
/** Move constructor. After the move, 'InValue' is guaranteed to be empty. */
@ -157,7 +155,7 @@ public:
Impl.BlocksMax = Impl->CalculateSlackReserve(NumBlocks());
Impl.Pointer = Impl->Allocate(MaxBlocks());
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(BlockType));
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(FBlockType));
}
}
@ -188,7 +186,7 @@ public:
Impl.BlocksMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(MaxBlocks());
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(BlockType));
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(FBlockType));
return *this;
}
@ -197,7 +195,7 @@ public:
Impl.BitsetNum = InValue.Num();
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(BlockType));
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(FBlockType));
return *this;
}
@ -247,14 +245,14 @@ public:
Impl.BlocksMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(MaxBlocks());
for (Reference Ref : *this) Ref = *First++;
for (FReference Ref : *this) Ref = *First++;
return *this;
}
Impl.BitsetNum = GetNum(IL);
for (Reference Ref : *this) Ref = *First++;
for (FReference Ref : *this) Ref = *First++;
return *this;
}
@ -271,7 +269,7 @@ public:
if (LHS.Impl.Pointer[Index] != RHS.Impl.Pointer[Index]) return false;
}
const BlockType LastBlockBitmask = LHS.Num() % BlockWidth != 0 ? (1ull << LHS.Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = LHS.Num() % BlockWidth != 0 ? (1ull << LHS.Num() % BlockWidth) - 1 : -1;
return (LHS.Impl.Pointer[LHS.NumBlocks() - 1] & LastBlockBitmask) == (RHS.Impl.Pointer[LHS.NumBlocks() - 1] & LastBlockBitmask);
}
@ -301,7 +299,7 @@ public:
Impl.Pointer[Index] &= InValue.Impl.Pointer[Index];
}
const BlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
Impl.Pointer[LastBlock] &= InValue.Impl.Pointer[LastBlock] & LastBlockBitmask;
@ -339,7 +337,7 @@ public:
Impl.Pointer[Index] |= InValue.Impl.Pointer[Index];
}
const BlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
Impl.Pointer[LastBlock] |= InValue.Impl.Pointer[LastBlock] & LastBlockBitmask;
}
@ -372,7 +370,7 @@ public:
Impl.Pointer[Index] ^= InValue.Impl.Pointer[Index];
}
const BlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
Impl.Pointer[LastBlock] ^= InValue.Impl.Pointer[LastBlock] & LastBlockBitmask;
}
@ -473,7 +471,7 @@ public:
if (Impl.Pointer[Index] != -1) return false;
}
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
return (Impl.Pointer[NumBlocks() - 1] | ~LastBlockBitmask) == -1;
}
@ -488,7 +486,7 @@ public:
if (Impl.Pointer[Index] != 0) return true;
}
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
return (Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask) != 0;
}
@ -503,24 +501,24 @@ public:
size_t Result = 0;
constexpr auto BlockCount = [](BlockType Block)
constexpr auto BlockCount = [](FBlockType Block)
{
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
if constexpr (sizeof(BlockType) == sizeof(uint8))
if constexpr (sizeof(FBlockType) == sizeof(uint8))
{
Block = (Block & 0x55ull) + ((Block >> 1) & 0x55ull);
Block = (Block & 0x33ull) + ((Block >> 2) & 0x33ull);
Block = (Block & 0x0Full) + ((Block >> 4) & 0x0Full);
}
else if constexpr (sizeof(BlockType) == sizeof(uint16))
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
{
Block = (Block & 0x5555ull) + ((Block >> 1) & 0x5555ull);
Block = (Block & 0x3333ull) + ((Block >> 2) & 0x3333ull);
Block = (Block & 0x0F0Full) + ((Block >> 4) & 0x0F0Full);
Block = (Block & 0x00FFull) + ((Block >> 8) & 0x00FFull);
}
else if constexpr (sizeof(BlockType) == sizeof(uint32))
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
{
Block = (Block & 0x55555555ull) + ((Block >> 1) & 0x55555555ull);
Block = (Block & 0x33333333ull) + ((Block >> 2) & 0x33333333ull);
@ -528,7 +526,7 @@ public:
Block = (Block & 0x00FF00FFull) + ((Block >> 8) & 0x00FF00FFull);
Block = (Block & 0x0000FFFFull) + ((Block >> 16) & 0x0000FFFFull);
}
else if constexpr (sizeof(BlockType) == sizeof(uint64))
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
{
Block = (Block & 0x5555555555555555ull) + ((Block >> 1) & 0x5555555555555555ull);
Block = (Block & 0x3333333333333333ull) + ((Block >> 2) & 0x3333333333333333ull);
@ -547,7 +545,7 @@ public:
Result += BlockCount(Impl.Pointer[Index]);
}
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
Result += BlockCount(Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask);
@ -557,7 +555,7 @@ public:
/** Sets all bits to true. */
TBitset& Set(bool InValue = true)
{
Memory::Memset(Impl.Pointer, static_cast<uint8>(InValue ? -1 : 0), NumBlocks() * sizeof(BlockType));
Memory::Memset(Impl.Pointer, static_cast<uint8>(InValue ? -1 : 0), NumBlocks() * sizeof(FBlockType));
return *this;
}
@ -591,17 +589,17 @@ public:
checkf(Impl.Pointer[Index] != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
}
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const BlockType LastBlock = Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask;
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlock = Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask;
checkf(LastBlock != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
}
uint64 Result = 0;
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
if constexpr (sizeof(BlockType) == sizeof(uint8))
if constexpr (sizeof(FBlockType) == sizeof(uint8))
{
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
Result |= static_cast<uint64>(Impl.Pointer[1]) << 8;
@ -612,19 +610,19 @@ public:
Result |= static_cast<uint64>(Impl.Pointer[6]) << 48;
Result |= static_cast<uint64>(Impl.Pointer[7]) << 56;
}
else if constexpr (sizeof(BlockType) == sizeof(uint16))
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
{
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
Result |= static_cast<uint64>(Impl.Pointer[1]) << 16;
Result |= static_cast<uint64>(Impl.Pointer[2]) << 32;
Result |= static_cast<uint64>(Impl.Pointer[3]) << 48;
}
else if constexpr (sizeof(BlockType) == sizeof(uint32))
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
{
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
Result |= static_cast<uint64>(Impl.Pointer[1]) << 32;
}
else if constexpr (sizeof(BlockType) == sizeof(uint64))
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
{
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
}
@ -661,7 +659,7 @@ public:
if (NumToAllocate != MaxBlocks())
{
BlockType* OldAllocation = Impl.Pointer;
FBlockType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = NumBlocks();
Impl.BitsetNum = InCount;
@ -670,11 +668,11 @@ public:
if (NumToDestruct <= Num())
{
Memory::Memcpy(Impl.Pointer, OldAllocation, NumToDestruct * sizeof(BlockType));
Memory::Memcpy(Impl.Pointer, OldAllocation, NumToDestruct * sizeof(FBlockType));
}
else
{
Memory::Memcpy(Impl.Pointer, OldAllocation, BlocksCount * sizeof(BlockType));
Memory::Memcpy(Impl.Pointer, OldAllocation, BlocksCount * sizeof(FBlockType));
}
Impl->Deallocate(OldAllocation);
@ -697,12 +695,12 @@ public:
NumToAllocate = NumToAllocate > MaxBlocks() ? Impl->CalculateSlackGrow(BlocksCount, MaxBlocks()) : NumToAllocate;
NumToAllocate = NumToAllocate < MaxBlocks() ? (bAllowShrinking ? Impl->CalculateSlackShrink(BlocksCount, MaxBlocks()) : MaxBlocks()) : NumToAllocate;
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const BlockType BlocksValueToSet = static_cast<BlockType>(InValue ? -1 : 0);
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const FBlockType BlocksValueToSet = static_cast<FBlockType>(InValue ? -1 : 0);
if (NumToAllocate != MaxBlocks())
{
BlockType* OldAllocation = Impl.Pointer;
FBlockType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = NumBlocks();
Impl.BitsetNum = InCount;
@ -713,16 +711,16 @@ public:
{
if (NumToDestruct != 0)
{
Memory::Memcpy(Impl.Pointer, OldAllocation, (NumToDestruct - 1) * sizeof(BlockType));
Memory::Memcpy(Impl.Pointer, OldAllocation, (NumToDestruct - 1) * sizeof(FBlockType));
Impl.Pointer[NumToDestruct - 1] = OldAllocation[NumToDestruct - 1] & LastBlockBitmask | BlocksValueToSet & ~LastBlockBitmask;
}
Memory::Memset(Impl.Pointer + NumToDestruct, static_cast<uint8>(BlocksValueToSet), (BlocksCount - NumToDestruct) * sizeof(BlockType));
Memory::Memset(Impl.Pointer + NumToDestruct, static_cast<uint8>(BlocksValueToSet), (BlocksCount - NumToDestruct) * sizeof(FBlockType));
}
else
{
Memory::Memcpy(Impl.Pointer, OldAllocation, BlocksCount * sizeof(BlockType));
Memory::Memcpy(Impl.Pointer, OldAllocation, BlocksCount * sizeof(FBlockType));
}
Impl->Deallocate(OldAllocation);
@ -739,7 +737,7 @@ public:
Impl.Pointer[NumBlocks() - 1] = Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask | BlocksValueToSet & ~LastBlockBitmask;
}
Memory::Memset(Impl.Pointer + NumBlocks(), static_cast<uint8>(BlocksValueToSet), (BlocksCount - NumBlocks()) * sizeof(BlockType));
Memory::Memset(Impl.Pointer + NumBlocks(), static_cast<uint8>(BlocksValueToSet), (BlocksCount - NumBlocks()) * sizeof(FBlockType));
}
Impl.BitsetNum = InCount;
@ -753,14 +751,14 @@ public:
const size_t BlocksCount = (InCount + BlockWidth - 1) / BlockWidth;
const size_t NumToAllocate = Impl->CalculateSlackReserve(BlocksCount);
BlockType* OldAllocation = Impl.Pointer;
FBlockType* OldAllocation = Impl.Pointer;
check(NumToAllocate > MaxBlocks());
Impl.BlocksMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(MaxBlocks());
Memory::Memcpy(Impl.Pointer, OldAllocation, NumBlocks() * sizeof(BlockType));
Memory::Memcpy(Impl.Pointer, OldAllocation, NumBlocks() * sizeof(FBlockType));
Impl->Deallocate(OldAllocation);
}
@ -774,31 +772,31 @@ public:
if (NumToAllocate == MaxBlocks()) return;
BlockType* OldAllocation = Impl.Pointer;
FBlockType* OldAllocation = Impl.Pointer;
Impl.BitsetNum = NumToAllocate * BlockWidth;
Impl.Pointer = Impl->Allocate(MaxBlocks());
Memory::Memcpy(Impl.Pointer, OldAllocation, NumBlocks() * sizeof(BlockType));
Memory::Memcpy(Impl.Pointer, OldAllocation, NumBlocks() * sizeof(FBlockType));
Impl->Deallocate(OldAllocation);
}
/** @return The pointer to the underlying element storage. */
NODISCARD FORCEINLINE BlockType* GetData() { return Impl.Pointer; }
NODISCARD FORCEINLINE const BlockType* GetData() const { return Impl.Pointer; }
NODISCARD FORCEINLINE FBlockType* GetData() { return Impl.Pointer; }
NODISCARD FORCEINLINE const FBlockType* GetData() const { return Impl.Pointer; }
/** @return The iterator to the first or end bit. */
NODISCARD FORCEINLINE Iterator Begin() { return Iterator(this, Impl.Pointer, 0); }
NODISCARD FORCEINLINE ConstIterator Begin() const { return ConstIterator(this, Impl.Pointer, 0); }
NODISCARD FORCEINLINE Iterator End() { return Iterator(this, Impl.Pointer, Num()); }
NODISCARD FORCEINLINE ConstIterator End() const { return ConstIterator(this, Impl.Pointer, Num()); }
NODISCARD FORCEINLINE FIterator Begin() { return FIterator(this, Impl.Pointer, 0); }
NODISCARD FORCEINLINE FConstIterator Begin() const { return FConstIterator(this, Impl.Pointer, 0); }
NODISCARD FORCEINLINE FIterator End() { return FIterator(this, Impl.Pointer, Num()); }
NODISCARD FORCEINLINE FConstIterator End() const { return FConstIterator(this, Impl.Pointer, Num()); }
/** @return The reverse iterator to the first or end bit. */
NODISCARD FORCEINLINE ReverseIterator RBegin() { return ReverseIterator(End()); }
NODISCARD FORCEINLINE ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
NODISCARD FORCEINLINE ReverseIterator REnd() { return ReverseIterator(Begin()); }
NODISCARD FORCEINLINE ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); }
NODISCARD FORCEINLINE FReverseIterator RBegin() { return FReverseIterator(End()); }
NODISCARD FORCEINLINE FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
NODISCARD FORCEINLINE FReverseIterator REnd() { return FReverseIterator(Begin()); }
NODISCARD FORCEINLINE FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
/** @return The number of bits in the bitset. */
NODISCARD FORCEINLINE size_t Num() const { return Impl.BitsetNum; }
@ -816,17 +814,17 @@ public:
NODISCARD FORCEINLINE bool IsEmpty() const { return Num() == 0; }
/** @return true if the iterator is valid, false otherwise. */
NODISCARD FORCEINLINE bool IsValidIterator(ConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
NODISCARD FORCEINLINE bool IsValidIterator(FConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
/** @return The reference to the requested bit. */
NODISCARD FORCEINLINE Reference operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
NODISCARD FORCEINLINE ConstReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
NODISCARD FORCEINLINE FReference operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
NODISCARD FORCEINLINE FConstReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
/** @return The reference to the first or last bit. */
NODISCARD FORCEINLINE Reference Front() { return *Begin(); }
NODISCARD FORCEINLINE ConstReference Front() const { return *Begin(); }
NODISCARD FORCEINLINE Reference Back() { return *(End() - 1); }
NODISCARD FORCEINLINE ConstReference Back() const { return *(End() - 1); }
NODISCARD FORCEINLINE FReference Front() { return *Begin(); }
NODISCARD FORCEINLINE FConstReference Front() const { return *Begin(); }
NODISCARD FORCEINLINE FReference Back() { return *(End() - 1); }
NODISCARD FORCEINLINE FConstReference Back() const { return *(End() - 1); }
/** Erases all bits from the bitset. After this call, Num() returns zero. */
void Reset(bool bAllowShrinking = true)
@ -859,7 +857,7 @@ public:
Result = HashCombine(Result, GetTypeHash(A.Impl.Pointer[Index]));
}
const BlockType LastBlockBitmask = A.Num() % BlockWidth != 0 ? (1ull << A.Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = A.Num() % BlockWidth != 0 ? (1ull << A.Num() % BlockWidth) - 1 : -1;
return HashCombine(Result, GetTypeHash(A.Impl.Pointer[A.NumBlocks() - 1] & LastBlockBitmask));
}
@ -889,27 +887,27 @@ public:
private:
ALLOCATOR_WRAPPER_BEGIN(AllocatorType, BlockType, Impl)
ALLOCATOR_WRAPPER_BEGIN(FAllocatorType, FBlockType, Impl)
{
size_t BitsetNum;
size_t BlocksMax;
BlockType* Pointer;
FBlockType* Pointer;
}
ALLOCATOR_WRAPPER_END(AllocatorType, BlockType, Impl)
ALLOCATOR_WRAPPER_END(FAllocatorType, FBlockType, Impl)
public:
class Reference final : private FSingleton
class FReference final : private FSingleton
{
public:
FORCEINLINE Reference& operator=(bool InValue) { Data = (Data & ~Mask) | (InValue ? Mask : 0); return *this; }
FORCEINLINE FReference& operator=(bool InValue) { Data = (Data & ~Mask) | (InValue ? Mask : 0); return *this; }
FORCEINLINE Reference& operator=(const Reference& InValue) { *this = static_cast<bool>(InValue); return *this; }
FORCEINLINE FReference& operator=(const FReference& InValue) { *this = static_cast<bool>(InValue); return *this; }
FORCEINLINE Reference& operator&=(bool InValue) { Data &= InValue ? -1 : ~Mask; return *this; }
FORCEINLINE Reference& operator|=(bool InValue) { Data |= InValue ? Mask : 0; return *this; }
FORCEINLINE Reference& operator^=(bool InValue) { *this = InValue ^ *this; return *this; }
FORCEINLINE FReference& operator&=(bool InValue) { Data &= InValue ? -1 : ~Mask; return *this; }
FORCEINLINE FReference& operator|=(bool InValue) { Data |= InValue ? Mask : 0; return *this; }
FORCEINLINE FReference& operator^=(bool InValue) { *this = InValue ^ *this; return *this; }
FORCEINLINE bool operator~() const { return !*this; }
@ -917,14 +915,14 @@ public:
private:
FORCEINLINE Reference(BlockType& InData, BlockType InMask)
FORCEINLINE FReference(FBlockType& InData, FBlockType InMask)
: Data(InData), Mask(InMask)
{ }
BlockType& Data;
BlockType Mask;
FBlockType& Data;
FBlockType Mask;
friend Iterator;
friend FIterator;
};
@ -935,7 +933,7 @@ private:
{
public:
using ElementType = bool;
using FElementType = bool;
FORCEINLINE TIteratorImpl() = default;
@ -958,8 +956,8 @@ private:
NODISCARD friend FORCEINLINE strong_ordering operator<=>(const TIteratorImpl& LHS, const TIteratorImpl& RHS) { check(LHS.Pointer == RHS.Pointer); return LHS.BitOffset <=> RHS.BitOffset; }
NODISCARD FORCEINLINE Reference operator*() const requires (!bConst) { CheckThis(true); return Reference(*(Pointer + BitOffset / BlockWidth), 1ull << BitOffset % BlockWidth); }
NODISCARD FORCEINLINE ConstReference operator*() const requires ( bConst) { CheckThis(true); return (*(Pointer + BitOffset / BlockWidth) & (1ull << BitOffset % BlockWidth)); }
NODISCARD FORCEINLINE FReference operator*() const requires (!bConst) { CheckThis(true); return FReference(*(Pointer + BitOffset / BlockWidth), 1ull << BitOffset % BlockWidth); }
NODISCARD FORCEINLINE FConstReference operator*() const requires ( bConst) { CheckThis(true); return (*(Pointer + BitOffset / BlockWidth) & (1ull << BitOffset % BlockWidth)); }
NODISCARD FORCEINLINE auto operator[](ptrdiff Index) const { TIteratorImpl Temp = *this + Index; return *Temp; }
@ -985,17 +983,17 @@ private:
const TBitset* Owner = nullptr;
# endif
using BlockPtr = TConditional<bConst, const BlockType*, BlockType*>;
using FBlockPtr = TConditional<bConst, const FBlockType*, FBlockType*>;
BlockPtr Pointer = nullptr;
size_t BitOffset = 0;
FBlockPtr Pointer = nullptr;
size_t BitOffset = 0;
# if DO_CHECK
FORCEINLINE TIteratorImpl(const TBitset* InContainer, BlockPtr InPointer, size_t Offset)
FORCEINLINE TIteratorImpl(const TBitset* InContainer, FBlockPtr InPointer, size_t Offset)
: Owner(InContainer), Pointer(InPointer), BitOffset(Offset)
{ }
# else
FORCEINLINE TIteratorImpl(const TBitset* InContainer, BlockPtr InPointer, size_t Offset)
FORCEINLINE TIteratorImpl(const TBitset* InContainer, FBlockPtr InPointer, size_t Offset)
: Pointer(InPointer), BitOffset(Offset)
{ }
# endif

View File

@ -28,20 +28,20 @@ private:
public:
using ElementType = T;
using AllocatorType = Allocator;
using FElementType = T;
using FAllocatorType = Allocator;
using Reference = T&;
using ConstReference = const T&;
using FReference = T&;
using FConstReference = const T&;
using Iterator = TIteratorImpl<false>;
using ConstIterator = TIteratorImpl<true >;
using FIterator = TIteratorImpl<false>;
using FConstIterator = TIteratorImpl<true >;
using ReverseIterator = TReverseIterator< Iterator>;
using ConstReverseIterator = TReverseIterator<ConstIterator>;
using FReverseIterator = TReverseIterator< FIterator>;
using FConstReverseIterator = TReverseIterator<FConstIterator>;
static_assert(CBidirectionalIterator< Iterator>);
static_assert(CBidirectionalIterator<ConstIterator>);
static_assert(CBidirectionalIterator< FIterator>);
static_assert(CBidirectionalIterator<FConstIterator>);
/** Default constructor. Constructs an empty container with a default-constructed allocator. */
TList()
@ -54,7 +54,7 @@ public:
}
/** Constructs the container with 'Count' default instances of T. */
explicit TList(size_t Count) requires (CDefaultConstructible<ElementType>) : TList()
explicit TList(size_t Count) requires (CDefaultConstructible<FElementType>) : TList()
{
FNode* EndNode = Impl.HeadNode->PrevNode;
@ -75,12 +75,12 @@ public:
}
/** Constructs the container with 'Count' copies of elements with 'InValue'. */
TList(size_t Count, const ElementType& InValue) requires (CCopyable<ElementType>)
TList(size_t Count, const FElementType& InValue) requires (CCopyable<FElementType>)
: TList(MakeCountedConstantIterator(InValue, Count), DefaultSentinel)
{ }
/** Constructs the container with the contents of the range ['First', 'Last'). */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
TList(I First, S Last) : TList()
{
FNode* EndNode = Impl.HeadNode->PrevNode;
@ -102,13 +102,13 @@ public:
}
/** Copy constructor. Constructs the container with the copy of the contents of 'InValue'. */
FORCEINLINE TList(const TList& InValue) requires (CCopyConstructible<ElementType>) : TList(InValue.Begin(), InValue.End()) { }
FORCEINLINE TList(const TList& InValue) requires (CCopyConstructible<FElementType>) : TList(InValue.Begin(), InValue.End()) { }
/** Move constructor. After the move, 'InValue' is guaranteed to be empty. */
FORCEINLINE TList(TList&& InValue) : TList() { Swap(*this, InValue); }
/** Constructs the container with the contents of the initializer list. */
FORCEINLINE TList(initializer_list<ElementType> IL) requires (CCopyConstructible<ElementType>) : TList(Iteration::Begin(IL), Iteration::End(IL)) { }
FORCEINLINE TList(initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) : TList(Iteration::Begin(IL), Iteration::End(IL)) { }
/** Destructs the list. The destructors of the elements are called and the used storage is deallocated. */
~TList()
@ -129,12 +129,12 @@ public:
}
/** Copy assignment operator. Replaces the contents with a copy of the contents of 'InValue'. */
TList& operator=(const TList& InValue) requires (CCopyable<ElementType>)
TList& operator=(const TList& InValue) requires (CCopyable<FElementType>)
{
if (&InValue == this) UNLIKELY return *this;
Iterator ThisIter = Begin();
ConstIterator OtherIter = InValue.Begin();
FIterator ThisIter = Begin();
FConstIterator OtherIter = InValue.Begin();
while (ThisIter != End() && OtherIter != InValue.End())
{
@ -166,10 +166,10 @@ public:
FORCEINLINE TList& operator=(TList&& InValue) { Swap(*this, InValue); InValue.Reset(); return *this; }
/** Replaces the contents with those identified by initializer list. */
TList& operator=(initializer_list<ElementType> IL) requires (CCopyable<ElementType>)
TList& operator=(initializer_list<FElementType> IL) requires (CCopyable<FElementType>)
{
Iterator ThisIter = Begin();
const ElementType* OtherIter = Iteration::Begin(IL);
FIterator ThisIter = Begin();
const FElementType* OtherIter = Iteration::Begin(IL);
while (ThisIter != End() && OtherIter != Iteration::End(IL))
{
@ -198,12 +198,12 @@ public:
}
/** Compares the contents of two lists. */
NODISCARD friend bool operator==(const TList& LHS, const TList& RHS) requires (CWeaklyEqualityComparable<ElementType>)
NODISCARD friend bool operator==(const TList& LHS, const TList& RHS) requires (CWeaklyEqualityComparable<FElementType>)
{
if (LHS.Num() != RHS.Num()) return false;
ConstIterator LHSIter = LHS.Begin();
ConstIterator RHSIter = RHS.Begin();
FConstIterator LHSIter = LHS.Begin();
FConstIterator RHSIter = RHS.Begin();
while (LHSIter != LHS.End())
{
@ -219,10 +219,10 @@ public:
}
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
NODISCARD friend auto operator<=>(const TList& LHS, const TList& RHS) requires (CSynthThreeWayComparable<ElementType>)
NODISCARD friend auto operator<=>(const TList& LHS, const TList& RHS) requires (CSynthThreeWayComparable<FElementType>)
{
ConstIterator LHSIter = LHS.Begin();
ConstIterator RHSIter = RHS.Begin();
FConstIterator LHSIter = LHS.Begin();
FConstIterator RHSIter = RHS.Begin();
while (LHSIter != LHS.End() && RHSIter != RHS.End())
{
@ -236,22 +236,22 @@ public:
}
/** Inserts 'InValue' before 'Iter' in the container. */
FORCEINLINE Iterator Insert(ConstIterator Iter, const ElementType& InValue) requires (CCopyConstructible<ElementType>) { return Emplace(Iter, InValue); }
FORCEINLINE FIterator Insert(FConstIterator Iter, const FElementType& InValue) requires (CCopyConstructible<FElementType>) { return Emplace(Iter, InValue); }
/** Inserts 'InValue' before 'Iter' in the container. */
FORCEINLINE Iterator Insert(ConstIterator Iter, ElementType&& InValue) requires (CMoveConstructible<ElementType>) { return Emplace(Iter, MoveTemp(InValue)); }
FORCEINLINE FIterator Insert(FConstIterator Iter, FElementType&& InValue) requires (CMoveConstructible<FElementType>) { return Emplace(Iter, MoveTemp(InValue)); }
/** Inserts 'Count' copies of the 'InValue' before 'Iter' in the container. */
Iterator Insert(ConstIterator Iter, size_t Count, const ElementType& InValue) requires (CCopyConstructible<ElementType>)
FIterator Insert(FConstIterator Iter, size_t Count, const FElementType& InValue) requires (CCopyConstructible<FElementType>)
{
return Insert(Iter, MakeCountedConstantIterator(InValue, Count), DefaultSentinel);
}
/** Inserts elements from range ['First', 'Last') before 'Iter'. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
Iterator Insert(ConstIterator Iter, I First, S Last)
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
FIterator Insert(FConstIterator Iter, I First, S Last)
{
if (First == Last) return Iterator(Iter.Pointer);
if (First == Last) return FIterator(Iter.Pointer);
FNode* InsertNode = Iter.Pointer->PrevNode;
@ -279,15 +279,15 @@ public:
InsertNode->NextNode = Iter.Pointer;
Iter.Pointer->PrevNode = InsertNode;
return Iterator(FirstNode);
return FIterator(FirstNode);
}
/** Inserts elements from initializer list before 'Iter' in the container. */
FORCEINLINE Iterator Insert(ConstIterator Iter, initializer_list<ElementType> IL) requires (CCopyConstructible<ElementType>) { return Insert(Iter, Iteration::Begin(IL), Iteration::End(IL)); }
FORCEINLINE FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) { return Insert(Iter, Iteration::Begin(IL), Iteration::End(IL)); }
/** Inserts a new element into the container directly before 'Iter'. */
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...>)
Iterator Emplace(ConstIterator Iter, Ts&&... Args)
template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...>)
FIterator Emplace(FConstIterator Iter, Ts&&... Args)
{
FNode* Node = new (Impl->Allocate(1)) FNode(InPlace, Forward<Ts>(Args)...);
@ -299,11 +299,11 @@ public:
Node->PrevNode->NextNode = Node;
Node->NextNode->PrevNode = Node;
return Iterator(Node);
return FIterator(Node);
}
/** Removes the element at 'Iter' in the container. */
Iterator Erase(ConstIterator Iter)
FIterator Erase(FConstIterator Iter)
{
FNode* NodeToErase = Iter.Pointer;
@ -319,11 +319,11 @@ public:
--Impl.ListNum;
return Iterator(NextNode);
return FIterator(NextNode);
}
/** Removes the elements in the range ['First', 'Last') in the container. */
Iterator Erase(ConstIterator First, ConstIterator Last)
FIterator Erase(FConstIterator First, FConstIterator Last)
{
FNode* FirstToErase = First.Pointer;
FNode* LastToErase = Last.Pointer;
@ -343,43 +343,43 @@ public:
FirstToErase = NextNode;
}
return Iterator(LastToErase);
return FIterator(LastToErase);
}
/** Appends the given element value to the end of the container. */
FORCEINLINE void PushBack(const ElementType& InValue) requires (CCopyConstructible<ElementType>) { EmplaceBack(InValue); }
FORCEINLINE void PushBack(const FElementType& InValue) requires (CCopyConstructible<FElementType>) { EmplaceBack(InValue); }
/** Appends the given element value to the end of the container. */
FORCEINLINE void PushBack(ElementType&& InValue) requires (CMoveConstructible<ElementType>) { EmplaceBack(MoveTemp(InValue)); }
FORCEINLINE void PushBack(FElementType&& InValue) requires (CMoveConstructible<FElementType>) { EmplaceBack(MoveTemp(InValue)); }
/** Appends a new element to the end of the container. */
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...>)
FORCEINLINE Reference EmplaceBack(Ts&&... Args) { return *Emplace(End(), Forward<Ts>(Args)...); }
template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...>)
FORCEINLINE FReference EmplaceBack(Ts&&... Args) { return *Emplace(End(), Forward<Ts>(Args)...); }
/** Removes the last element of the container. The list cannot be empty. */
FORCEINLINE void PopBack() { Erase(--End()); }
/** Prepends the given element value to the beginning of the container. */
FORCEINLINE void PushFront(const ElementType& InValue) requires (CCopyConstructible<ElementType>) { EmplaceFront(InValue); }
FORCEINLINE void PushFront(const FElementType& InValue) requires (CCopyConstructible<FElementType>) { EmplaceFront(InValue); }
/** Prepends the given element value to the beginning of the container. */
FORCEINLINE void PushFront(ElementType&& InValue) requires (CMoveConstructible<ElementType>) { EmplaceFront(MoveTemp(InValue)); }
FORCEINLINE void PushFront(FElementType&& InValue) requires (CMoveConstructible<FElementType>) { EmplaceFront(MoveTemp(InValue)); }
/** Prepends a new element to the beginning of the container. */
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...>)
FORCEINLINE Reference EmplaceFront(Ts&&... Args) { return *Emplace(Begin(), Forward<Ts>(Args)...); }
template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...>)
FORCEINLINE FReference EmplaceFront(Ts&&... Args) { return *Emplace(Begin(), Forward<Ts>(Args)...); }
/** Removes the first element of the container. The list cannot be empty. */
FORCEINLINE void PopFront() { Erase(Begin()); }
/** Resizes the container to contain 'Count' elements. Additional default elements are appended. */
void SetNum(size_t Count) requires (CDefaultConstructible<ElementType>)
void SetNum(size_t Count) requires (CDefaultConstructible<FElementType>)
{
if (Count == Impl.ListNum) return;
if (Count < Impl.ListNum)
{
Iterator First = End();
FIterator First = End();
Iteration::Advance(First, Count - Impl.ListNum);
@ -409,13 +409,13 @@ public:
}
/** Resizes the container to contain 'Count' elements. Additional copies of 'InValue' are appended. */
void SetNum(size_t Count, const ElementType& InValue) requires (CCopyConstructible<ElementType>)
void SetNum(size_t Count, const FElementType& InValue) requires (CCopyConstructible<FElementType>)
{
if (Count == Impl.ListNum) return;
if (Count < Impl.ListNum)
{
Iterator First = End();
FIterator First = End();
Iteration::Advance(First, Count - Impl.ListNum);
@ -445,16 +445,16 @@ public:
}
/** @return The iterator to the first or end element. */
NODISCARD FORCEINLINE Iterator Begin() { return Iterator(Impl.HeadNode->NextNode); }
NODISCARD FORCEINLINE ConstIterator Begin() const { return ConstIterator(Impl.HeadNode->NextNode); }
NODISCARD FORCEINLINE Iterator End() { return Iterator(Impl.HeadNode); }
NODISCARD FORCEINLINE ConstIterator End() const { return ConstIterator(Impl.HeadNode); }
NODISCARD FORCEINLINE FIterator Begin() { return FIterator(Impl.HeadNode->NextNode); }
NODISCARD FORCEINLINE FConstIterator Begin() const { return FConstIterator(Impl.HeadNode->NextNode); }
NODISCARD FORCEINLINE FIterator End() { return FIterator(Impl.HeadNode); }
NODISCARD FORCEINLINE FConstIterator End() const { return FConstIterator(Impl.HeadNode); }
/** @return The reverse iterator to the first or end element. */
NODISCARD FORCEINLINE ReverseIterator RBegin() { return ReverseIterator(End()); }
NODISCARD FORCEINLINE ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
NODISCARD FORCEINLINE ReverseIterator REnd() { return ReverseIterator(Begin()); }
NODISCARD FORCEINLINE ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); }
NODISCARD FORCEINLINE FReverseIterator RBegin() { return FReverseIterator(End()); }
NODISCARD FORCEINLINE FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
NODISCARD FORCEINLINE FReverseIterator REnd() { return FReverseIterator(Begin()); }
NODISCARD FORCEINLINE FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
/** @return The number of elements in the container. */
NODISCARD FORCEINLINE size_t Num() const { return Impl.ListNum; }
@ -463,7 +463,7 @@ public:
NODISCARD FORCEINLINE bool IsEmpty() const { return Num() == 0; }
/** @return true if the iterator is valid, false otherwise. */
NODISCARD FORCEINLINE bool IsValidIterator(ConstIterator Iter) const
NODISCARD FORCEINLINE bool IsValidIterator(FConstIterator Iter) const
{
FNode* Current = Impl.HeadNode;
@ -481,10 +481,10 @@ public:
}
/** @return The reference to the first or last element. */
NODISCARD FORCEINLINE ElementType& Front() { return *Begin(); }
NODISCARD FORCEINLINE const ElementType& Front() const { return *Begin(); }
NODISCARD FORCEINLINE ElementType& Back() { return *(End() - 1); }
NODISCARD FORCEINLINE const ElementType& Back() const { return *(End() - 1); }
NODISCARD FORCEINLINE FElementType& Front() { return *Begin(); }
NODISCARD FORCEINLINE const FElementType& Front() const { return *Begin(); }
NODISCARD FORCEINLINE FElementType& Back() { return *(End() - 1); }
NODISCARD FORCEINLINE const FElementType& Back() const { return *(End() - 1); }
/** Erases all elements from the container. After this call, Num() returns zero. */
void Reset()
@ -508,11 +508,11 @@ public:
}
/** Overloads the GetTypeHash algorithm for TList. */
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TList& A) requires (CHashable<ElementType>)
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TList& A) requires (CHashable<FElementType>)
{
size_t Result = 0;
for (const ElementType& Element : A)
for (const FElementType& Element : A)
{
Result = HashCombine(Result, GetTypeHash(Element));
}
@ -535,7 +535,7 @@ private:
{
FNode* PrevNode;
FNode* NextNode;
ElementType Value;
FElementType Value;
FORCEINLINE FNode() = default;
@ -543,21 +543,21 @@ private:
FORCEINLINE FNode(FInPlace, Ts&&... Args) : Value(Forward<Ts>(Args)...) { }
};
static_assert(CMultipleAllocator<AllocatorType, FNode>);
static_assert(CMultipleAllocator<FAllocatorType, FNode>);
ALLOCATOR_WRAPPER_BEGIN(AllocatorType, FNode, Impl)
ALLOCATOR_WRAPPER_BEGIN(FAllocatorType, FNode, Impl)
{
FNode* HeadNode;
size_t ListNum;
}
ALLOCATOR_WRAPPER_END(AllocatorType, FNode, Impl)
ALLOCATOR_WRAPPER_END(FAllocatorType, FNode, Impl)
template <bool bConst, typename U>
class TIteratorImpl final
{
public:
using ElementType = TRemoveCV<T>;
using FElementType = TRemoveCV<T>;
FORCEINLINE TIteratorImpl() = default;

View File

@ -25,22 +25,22 @@ private:
public:
using ElementType = T;
using FElementType = T;
using Reference = T&;
using ConstReference = const T&;
using FReference = T&;
using FConstReference = const T&;
using Iterator = TIteratorImpl<false>;
using ConstIterator = TIteratorImpl<true >;
using FIterator = TIteratorImpl<false>;
using FConstIterator = TIteratorImpl<true >;
using ReverseIterator = TReverseIterator< Iterator>;
using ConstReverseIterator = TReverseIterator<ConstIterator>;
using FReverseIterator = TReverseIterator< FIterator>;
using FConstReverseIterator = TReverseIterator<FConstIterator>;
static_assert(CContiguousIterator< Iterator>);
static_assert(CContiguousIterator<ConstIterator>);
static_assert(CContiguousIterator< FIterator>);
static_assert(CContiguousIterator<FConstIterator>);
/** Compares the contents of two arrays. */
NODISCARD friend constexpr bool operator==(const TStaticArray& LHS, const TStaticArray& RHS) requires (CWeaklyEqualityComparable<ElementType>)
NODISCARD friend constexpr bool operator==(const TStaticArray& LHS, const TStaticArray& RHS) requires (CWeaklyEqualityComparable<FElementType>)
{
if (LHS.Num() != RHS.Num()) return false;
@ -53,7 +53,7 @@ public:
}
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
NODISCARD friend constexpr auto operator<=>(const TStaticArray& LHS, const TStaticArray& RHS) requires (CSynthThreeWayComparable<ElementType>)
NODISCARD friend constexpr auto operator<=>(const TStaticArray& LHS, const TStaticArray& RHS) requires (CSynthThreeWayComparable<FElementType>)
{
const size_t NumToCompare = LHS.Num() < RHS.Num() ? LHS.Num() : RHS.Num();
@ -66,20 +66,20 @@ public:
}
/** @return The pointer to the underlying element storage. */
NODISCARD FORCEINLINE constexpr ElementType* GetData() { return _; }
NODISCARD FORCEINLINE constexpr const ElementType* GetData() const { return _; }
NODISCARD FORCEINLINE constexpr FElementType* GetData() { return _; }
NODISCARD FORCEINLINE constexpr const FElementType* GetData() const { return _; }
/** @return The iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr Iterator Begin() { return Iterator(this, _); }
NODISCARD FORCEINLINE constexpr ConstIterator Begin() const { return ConstIterator(this, _); }
NODISCARD FORCEINLINE constexpr Iterator End() { return Iterator(this, _ + Num()); }
NODISCARD FORCEINLINE constexpr ConstIterator End() const { return ConstIterator(this, _ + Num()); }
NODISCARD FORCEINLINE constexpr FIterator Begin() { return FIterator(this, _); }
NODISCARD FORCEINLINE constexpr FConstIterator Begin() const { return FConstIterator(this, _); }
NODISCARD FORCEINLINE constexpr FIterator End() { return FIterator(this, _ + Num()); }
NODISCARD FORCEINLINE constexpr FConstIterator End() const { return FConstIterator(this, _ + Num()); }
/** @return The reverse iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() { return ReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr ReverseIterator REnd() { return ReverseIterator(Begin()); }
NODISCARD FORCEINLINE constexpr ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); }
NODISCARD FORCEINLINE constexpr FReverseIterator RBegin() { return FReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr FReverseIterator REnd() { return FReverseIterator(Begin()); }
NODISCARD FORCEINLINE constexpr FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
/** @return The number of elements in the container. */
NODISCARD FORCEINLINE constexpr size_t Num() const { return N; }
@ -88,24 +88,24 @@ public:
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; }
/** @return true if the iterator is valid, false otherwise. */
NODISCARD FORCEINLINE constexpr bool IsValidIterator(ConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
NODISCARD FORCEINLINE constexpr bool IsValidIterator(FConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
/** @return The reference to the requested element. */
NODISCARD FORCEINLINE constexpr ElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return _[Index]; }
NODISCARD FORCEINLINE constexpr const ElementType& operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return _[Index]; }
NODISCARD FORCEINLINE constexpr FElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return _[Index]; }
NODISCARD FORCEINLINE constexpr const FElementType& operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return _[Index]; }
/** @return The reference to the first or last element. */
NODISCARD FORCEINLINE constexpr ElementType& Front() { return *Begin(); }
NODISCARD FORCEINLINE constexpr const ElementType& Front() const { return *Begin(); }
NODISCARD FORCEINLINE constexpr ElementType& Back() { return *(End() - 1); }
NODISCARD FORCEINLINE constexpr const ElementType& Back() const { return *(End() - 1); }
NODISCARD FORCEINLINE constexpr FElementType& Front() { return *Begin(); }
NODISCARD FORCEINLINE constexpr const FElementType& Front() const { return *Begin(); }
NODISCARD FORCEINLINE constexpr FElementType& Back() { return *(End() - 1); }
NODISCARD FORCEINLINE constexpr const FElementType& Back() const { return *(End() - 1); }
/** Overloads the GetTypeHash algorithm for TStaticArray. */
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(const TStaticArray& A) requires (CHashable<ElementType>)
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(const TStaticArray& A) requires (CHashable<FElementType>)
{
size_t Result = 0;
for (ConstIterator Iter = A.Begin(); Iter != A.End(); ++Iter)
for (FConstIterator Iter = A.Begin(); Iter != A.End(); ++Iter)
{
Result = HashCombine(Result, GetTypeHash(*Iter));
}
@ -114,7 +114,7 @@ public:
}
/** Overloads the Swap algorithm for TStaticArray. */
friend FORCEINLINE constexpr void Swap(TStaticArray& A, TStaticArray& B) requires (CSwappable<ElementType>) { Swap(A._, B._); }
friend FORCEINLINE constexpr void Swap(TStaticArray& A, TStaticArray& B) requires (CSwappable<FElementType>) { Swap(A._, B._); }
ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT
@ -127,7 +127,7 @@ private:
{
public:
using ElementType = TRemoveCV<T>;
using FElementType = TRemoveCV<T>;
FORCEINLINE constexpr TIteratorImpl() = default;
@ -224,6 +224,8 @@ NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END
// ReSharper disable CppInconsistentNaming
NAMESPACE_STD_BEGIN
// Support structure binding, should not be directly used.
@ -245,3 +247,5 @@ template <size_t Index, typename T, size_t N> FORCEINLINE constexpr decltype(aut
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END
// ReSharper restore CppInconsistentNaming

View File

@ -37,22 +37,22 @@ private:
public:
using BlockType = InBlockType;
using ElementType = bool;
using FBlockType = InBlockType;
using FElementType = bool;
class Reference;
using ConstReference = bool;
class FReference;
using FConstReference = bool;
using Iterator = TIteratorImpl<false>;
using ConstIterator = TIteratorImpl<true >;
using FIterator = TIteratorImpl<false>;
using FConstIterator = TIteratorImpl<true >;
using ReverseIterator = TReverseIterator< Iterator>;
using ConstReverseIterator = TReverseIterator<ConstIterator>;
using FReverseIterator = TReverseIterator< FIterator>;
using FConstReverseIterator = TReverseIterator<FConstIterator>;
static_assert(CRandomAccessIterator< Iterator>);
static_assert(CRandomAccessIterator<ConstIterator>);
static_assert(CRandomAccessIterator< FIterator>);
static_assert(CRandomAccessIterator<FConstIterator>);
static constexpr size_t BlockWidth = sizeof(BlockType) * 8;
static constexpr size_t BlockWidth = sizeof(FBlockType) * 8;
/** Default constructor. Constructs an empty bitset. */
FORCEINLINE constexpr TStaticBitset() = default;
@ -60,38 +60,38 @@ public:
/** Constructs a bitset from an integer. */
constexpr TStaticBitset(uint64 InValue)
{
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
if constexpr (sizeof(BlockType) == sizeof(uint8))
if constexpr (sizeof(FBlockType) == sizeof(uint8))
{
if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
if constexpr (N > 8) Impl[1] = static_cast<BlockType>(InValue >> 8);
if constexpr (N > 16) Impl[2] = static_cast<BlockType>(InValue >> 16);
if constexpr (N > 24) Impl[3] = static_cast<BlockType>(InValue >> 24);
if constexpr (N > 32) Impl[4] = static_cast<BlockType>(InValue >> 32);
if constexpr (N > 40) Impl[5] = static_cast<BlockType>(InValue >> 40);
if constexpr (N > 48) Impl[6] = static_cast<BlockType>(InValue >> 48);
if constexpr (N > 56) Impl[7] = static_cast<BlockType>(InValue >> 56);
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0);
if constexpr (N > 8) Impl[1] = static_cast<FBlockType>(InValue >> 8);
if constexpr (N > 16) Impl[2] = static_cast<FBlockType>(InValue >> 16);
if constexpr (N > 24) Impl[3] = static_cast<FBlockType>(InValue >> 24);
if constexpr (N > 32) Impl[4] = static_cast<FBlockType>(InValue >> 32);
if constexpr (N > 40) Impl[5] = static_cast<FBlockType>(InValue >> 40);
if constexpr (N > 48) Impl[6] = static_cast<FBlockType>(InValue >> 48);
if constexpr (N > 56) Impl[7] = static_cast<FBlockType>(InValue >> 56);
}
else if constexpr (sizeof(BlockType) == sizeof(uint16))
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
{
if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
if constexpr (N > 16) Impl[1] = static_cast<BlockType>(InValue >> 16);
if constexpr (N > 32) Impl[2] = static_cast<BlockType>(InValue >> 32);
if constexpr (N > 48) Impl[3] = static_cast<BlockType>(InValue >> 48);
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0);
if constexpr (N > 16) Impl[1] = static_cast<FBlockType>(InValue >> 16);
if constexpr (N > 32) Impl[2] = static_cast<FBlockType>(InValue >> 32);
if constexpr (N > 48) Impl[3] = static_cast<FBlockType>(InValue >> 48);
}
else if constexpr (sizeof(BlockType) == sizeof(uint32))
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
{
if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
if constexpr (N > 32) Impl[1] = static_cast<BlockType>(InValue >> 32);
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0);
if constexpr (N > 32) Impl[1] = static_cast<FBlockType>(InValue >> 32);
}
else if constexpr (sizeof(BlockType) == sizeof(uint64))
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
{
if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0);
}
else check_no_entry();
constexpr size_t BlockInteger = sizeof(uint64) / sizeof(BlockType);
constexpr size_t BlockInteger = sizeof(uint64) / sizeof(FBlockType);
if constexpr ((N + BlockWidth - 1) / BlockWidth <= BlockInteger) return;
@ -126,7 +126,7 @@ public:
if (LHS.Impl[Index] != RHS.Impl[Index]) return false;
}
const BlockType LastBlockBitmask = LHS.Num() % BlockWidth != 0 ? (1ull << LHS.Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = LHS.Num() % BlockWidth != 0 ? (1ull << LHS.Num() % BlockWidth) - 1 : -1;
return (LHS.Impl[LHS.NumBlocks() - 1] & LastBlockBitmask) == (RHS.Impl[LHS.NumBlocks() - 1] & LastBlockBitmask);
}
@ -269,7 +269,7 @@ public:
if (Impl[Index] != -1) return false;
}
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
return (Impl[NumBlocks() - 1] | ~LastBlockBitmask) == -1;
}
@ -284,7 +284,7 @@ public:
if (Impl[Index] != 0) return true;
}
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
return (Impl[NumBlocks() - 1] & LastBlockBitmask) != 0;
}
@ -299,24 +299,24 @@ public:
size_t Result = 0;
constexpr auto BlockCount = [](BlockType Block) constexpr
constexpr auto BlockCount = [](FBlockType Block) constexpr
{
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
if constexpr (sizeof(BlockType) == sizeof(uint8))
if constexpr (sizeof(FBlockType) == sizeof(uint8))
{
Block = (Block & 0x55ull) + ((Block >> 1) & 0x55ull);
Block = (Block & 0x33ull) + ((Block >> 2) & 0x33ull);
Block = (Block & 0x0Full) + ((Block >> 4) & 0x0Full);
}
else if constexpr (sizeof(BlockType) == sizeof(uint16))
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
{
Block = (Block & 0x5555ull) + ((Block >> 1) & 0x5555ull);
Block = (Block & 0x3333ull) + ((Block >> 2) & 0x3333ull);
Block = (Block & 0x0F0Full) + ((Block >> 4) & 0x0F0Full);
Block = (Block & 0x00FFull) + ((Block >> 8) & 0x00FFull);
}
else if constexpr (sizeof(BlockType) == sizeof(uint32))
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
{
Block = (Block & 0x55555555ull) + ((Block >> 1) & 0x55555555ull);
Block = (Block & 0x33333333ull) + ((Block >> 2) & 0x33333333ull);
@ -324,7 +324,7 @@ public:
Block = (Block & 0x00FF00FFull) + ((Block >> 8) & 0x00FF00FFull);
Block = (Block & 0x0000FFFFull) + ((Block >> 16) & 0x0000FFFFull);
}
else if constexpr (sizeof(BlockType) == sizeof(uint64))
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
{
Block = (Block & 0x5555555555555555ull) + ((Block >> 1) & 0x5555555555555555ull);
Block = (Block & 0x3333333333333333ull) + ((Block >> 2) & 0x3333333333333333ull);
@ -343,7 +343,7 @@ public:
Result += BlockCount(Impl[Index]);
}
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
Result += BlockCount(Impl[NumBlocks() - 1] & LastBlockBitmask);
@ -355,7 +355,7 @@ public:
{
for (size_t Index = 0; Index != NumBlocks(); ++Index)
{
Impl[Index] = static_cast<BlockType>(InValue ? -1 : 0);
Impl[Index] = static_cast<FBlockType>(InValue ? -1 : 0);
}
return *this;
@ -387,20 +387,20 @@ public:
{
for (size_t Index = 64 / BlockWidth; Index < NumBlocks() - 1; ++Index)
{
checkf(Impl.Pointer[Index] != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
checkf(Impl[Index] != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
}
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const BlockType LastBlock = Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask;
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlock = Impl[NumBlocks() - 1] & LastBlockBitmask;
checkf(LastBlock != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
}
uint64 Result = 0;
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
if constexpr (sizeof(BlockType) == sizeof(uint8))
if constexpr (sizeof(FBlockType) == sizeof(uint8))
{
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
if constexpr (N > 8) Result |= static_cast<uint64>(Impl[1]) << 8;
@ -411,19 +411,19 @@ public:
if constexpr (N > 48) Result |= static_cast<uint64>(Impl[6]) << 48;
if constexpr (N > 56) Result |= static_cast<uint64>(Impl[7]) << 56;
}
else if constexpr (sizeof(BlockType) == sizeof(uint16))
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
{
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
if constexpr (N > 16) Result |= static_cast<uint64>(Impl[1]) << 16;
if constexpr (N > 32) Result |= static_cast<uint64>(Impl[2]) << 32;
if constexpr (N > 48) Result |= static_cast<uint64>(Impl[3]) << 48;
}
else if constexpr (sizeof(BlockType) == sizeof(uint32))
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
{
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
if constexpr (N > 32) Result |= static_cast<uint64>(Impl[1]) << 32;
}
else if constexpr (sizeof(BlockType) == sizeof(uint64))
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
{
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
}
@ -435,20 +435,20 @@ public:
}
/** @return The pointer to the underlying element storage. */
NODISCARD FORCEINLINE constexpr BlockType* GetData() { return Impl; }
NODISCARD FORCEINLINE constexpr const BlockType* GetData() const { return Impl; }
NODISCARD FORCEINLINE constexpr FBlockType* GetData() { return Impl; }
NODISCARD FORCEINLINE constexpr const FBlockType* GetData() const { return Impl; }
/** @return The iterator to the first or end bit. */
NODISCARD FORCEINLINE constexpr Iterator Begin() { return Iterator(this, Impl, 0); }
NODISCARD FORCEINLINE constexpr ConstIterator Begin() const { return ConstIterator(this, Impl, 0); }
NODISCARD FORCEINLINE constexpr Iterator End() { return Iterator(this, Impl, Num()); }
NODISCARD FORCEINLINE constexpr ConstIterator End() const { return ConstIterator(this, Impl, Num()); }
NODISCARD FORCEINLINE constexpr FIterator Begin() { return FIterator(this, Impl, 0); }
NODISCARD FORCEINLINE constexpr FConstIterator Begin() const { return FConstIterator(this, Impl, 0); }
NODISCARD FORCEINLINE constexpr FIterator End() { return FIterator(this, Impl, Num()); }
NODISCARD FORCEINLINE constexpr FConstIterator End() const { return FConstIterator(this, Impl, Num()); }
/** @return The reverse iterator to the first or end bit. */
NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() { return ReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr ReverseIterator REnd() { return ReverseIterator(Begin()); }
NODISCARD FORCEINLINE constexpr ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); }
NODISCARD FORCEINLINE constexpr FReverseIterator RBegin() { return FReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr FReverseIterator REnd() { return FReverseIterator(Begin()); }
NODISCARD FORCEINLINE constexpr FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
/** @return The number of bits in the bitset. */
NODISCARD FORCEINLINE constexpr size_t Num() const { return N; }
@ -460,17 +460,17 @@ public:
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; }
/** @return true if the iterator is valid, false otherwise. */
NODISCARD FORCEINLINE constexpr bool IsValidIterator(ConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
NODISCARD FORCEINLINE constexpr bool IsValidIterator(FConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
/** @return The reference to the requested bit. */
NODISCARD FORCEINLINE constexpr Reference operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
NODISCARD FORCEINLINE constexpr ConstReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
NODISCARD FORCEINLINE constexpr FReference operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
NODISCARD FORCEINLINE constexpr FConstReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
/** @return The reference to the first or last bit. */
NODISCARD FORCEINLINE constexpr Reference Front() { return *Begin(); }
NODISCARD FORCEINLINE constexpr ConstReference Front() const { return *Begin(); }
NODISCARD FORCEINLINE constexpr Reference Back() { return *(End() - 1); }
NODISCARD FORCEINLINE constexpr ConstReference Back() const { return *(End() - 1); }
NODISCARD FORCEINLINE constexpr FReference Front() { return *Begin(); }
NODISCARD FORCEINLINE constexpr FConstReference Front() const { return *Begin(); }
NODISCARD FORCEINLINE constexpr FReference Back() { return *(End() - 1); }
NODISCARD FORCEINLINE constexpr FConstReference Back() const { return *(End() - 1); }
/** Overloads the GetTypeHash algorithm for TStaticBitset. */
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(const TStaticBitset& A)
@ -484,7 +484,7 @@ public:
Result = HashCombine(Result, GetTypeHash(A.Impl[Index]));
}
const BlockType LastBlockBitmask = A.Num() % BlockWidth != 0 ? (1ull << A.Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlockBitmask = A.Num() % BlockWidth != 0 ? (1ull << A.Num() % BlockWidth) - 1 : -1;
return HashCombine(Result, GetTypeHash(A.Impl[A.NumBlocks() - 1] & LastBlockBitmask));
}
@ -496,21 +496,21 @@ public:
private:
BlockType Impl[N != 0 ? (N + BlockWidth - 1) / BlockWidth : 1];
FBlockType Impl[N != 0 ? (N + BlockWidth - 1) / BlockWidth : 1];
public:
class Reference final : private FSingleton
class FReference final : private FSingleton
{
public:
FORCEINLINE constexpr Reference& operator=(bool InValue) { Data = (Data & ~Mask) | (InValue ? Mask : 0); return *this; }
FORCEINLINE constexpr FReference& operator=(bool InValue) { Data = (Data & ~Mask) | (InValue ? Mask : 0); return *this; }
FORCEINLINE constexpr Reference& operator=(const Reference& InValue) { *this = static_cast<bool>(InValue); return *this; }
FORCEINLINE constexpr FReference& operator=(const FReference& InValue) { *this = static_cast<bool>(InValue); return *this; }
FORCEINLINE constexpr Reference& operator&=(bool InValue) { Data &= InValue ? -1 : ~Mask; return *this; }
FORCEINLINE constexpr Reference& operator|=(bool InValue) { Data |= InValue ? Mask : 0; return *this; }
FORCEINLINE constexpr Reference& operator^=(bool InValue) { *this = InValue ^ *this; return *this; }
FORCEINLINE constexpr FReference& operator&=(bool InValue) { Data &= InValue ? -1 : ~Mask; return *this; }
FORCEINLINE constexpr FReference& operator|=(bool InValue) { Data |= InValue ? Mask : 0; return *this; }
FORCEINLINE constexpr FReference& operator^=(bool InValue) { *this = InValue ^ *this; return *this; }
FORCEINLINE constexpr bool operator~() const { return !*this; }
@ -518,14 +518,14 @@ public:
private:
FORCEINLINE constexpr Reference(BlockType& InData, BlockType InMask)
FORCEINLINE constexpr FReference(FBlockType& InData, FBlockType InMask)
: Data(InData), Mask(InMask)
{ }
BlockType& Data;
BlockType Mask;
FBlockType& Data;
FBlockType Mask;
friend Iterator;
friend FIterator;
};
@ -538,7 +538,7 @@ private:
public:
using ElementType = bool;
using FElementType = bool;
FORCEINLINE constexpr TIteratorImpl() = default;
@ -561,8 +561,8 @@ private:
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TIteratorImpl& LHS, const TIteratorImpl& RHS) { check(LHS.Pointer == RHS.Pointer); return LHS.BitOffset <=> RHS.BitOffset; }
NODISCARD FORCEINLINE constexpr Reference operator*() const requires (!bConst) { CheckThis(true); return Reference(*(Pointer + BitOffset / BlockWidth), 1ull << BitOffset % BlockWidth); }
NODISCARD FORCEINLINE constexpr ConstReference operator*() const requires ( bConst) { CheckThis(true); return (*(Pointer + BitOffset / BlockWidth) & (1ull << BitOffset % BlockWidth)); }
NODISCARD FORCEINLINE constexpr FReference operator*() const requires (!bConst) { CheckThis(true); return FReference(*(Pointer + BitOffset / BlockWidth), 1ull << BitOffset % BlockWidth); }
NODISCARD FORCEINLINE constexpr FConstReference operator*() const requires ( bConst) { CheckThis(true); return (*(Pointer + BitOffset / BlockWidth) & (1ull << BitOffset % BlockWidth)); }
NODISCARD FORCEINLINE constexpr auto operator[](ptrdiff Index) const { TIteratorImpl Temp = *this + Index; return *Temp; }
@ -588,17 +588,17 @@ private:
const TStaticBitset* Owner = nullptr;
# endif
using BlockPtr = TConditional<bConst, const BlockType*, BlockType*>;
using FBlockPtr = TConditional<bConst, const FBlockType*, FBlockType*>;
BlockPtr Pointer = nullptr;
size_t BitOffset = 0;
FBlockPtr Pointer = nullptr;
size_t BitOffset = 0;
# if DO_CHECK
FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, BlockPtr InPointer, size_t Offset)
FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, FBlockPtr InPointer, size_t Offset)
: Owner(InContainer), Pointer(InPointer), BitOffset(Offset)
{ }
# else
FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, BlockPtr InPointer, size_t Offset)
FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, FBlockPtr InPointer, size_t Offset)
: Pointer(InPointer), BitOffset(Offset)
{ }
# endif

View File

@ -33,7 +33,7 @@ struct IBidirectionalIterator /* : IForwardIterator<T> */
{
// ~Begin CForwardIterator.
using ElementType = TRemoveCVRef<T>;
using FElementType = TRemoveCVRef<T>;
IBidirectionalIterator();
IBidirectionalIterator(const IBidirectionalIterator&);

View File

@ -35,7 +35,7 @@ struct IContiguousIterator /* : IRandomAccessIterator<T> */
{
// ~Begin CRandomAccessIterator.
using ElementType = TRemoveCVRef<T>;
using FElementType = TRemoveCVRef<T>;
IContiguousIterator();
IContiguousIterator(const IContiguousIterator&);

View File

@ -18,8 +18,8 @@ NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_PRIVATE_BEGIN
template <typename T> class TCountedIteratorImpl { };
template <CIndirectlyReadable T> class TCountedIteratorImpl<T> { public: using ElementType = TIteratorElement<T>; };
template <typename T> class TCountedIteratorImpl { };
template <CIndirectlyReadable T> class TCountedIteratorImpl<T> { public: using FElementType = TIteratorElement<T>; };
NAMESPACE_PRIVATE_END
@ -34,7 +34,7 @@ class TCountedIterator final : public NAMESPACE_PRIVATE::TCountedIteratorImpl<I>
{
public:
using IteratorType = I;
using FIteratorType = I;
# if DO_CHECK
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<I>) : Length(1), MaxLength(0) { }
@ -48,7 +48,7 @@ public:
FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator&&) = default;
FORCEINLINE constexpr ~TCountedIterator() = default;
FORCEINLINE constexpr explicit TCountedIterator(IteratorType InValue, ptrdiff N) : Current(MoveTemp(InValue)) { check_code({ MaxLength = N; }); }
FORCEINLINE constexpr explicit TCountedIterator(FIteratorType InValue, ptrdiff N) : Current(MoveTemp(InValue)) { check_code({ MaxLength = N; }); }
template <CInputOrOutputIterator J> requires (!CSameAs<I, J> && CConstructibleFrom<I, const J&>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, I>) TCountedIterator(const TCountedIterator<J>& InValue)
@ -106,14 +106,14 @@ public:
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { LHS.CheckThis(); return -LHS.Num(); }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { RHS.CheckThis(); return RHS.Num(); }
NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { CheckThis(); return Current; }
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { CheckThis(); return MoveTemp(Current); }
NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; }
NODISCARD FORCEINLINE constexpr const FIteratorType& GetBase() const& { CheckThis(); return Current; }
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { CheckThis(); return MoveTemp(Current); }
NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; }
private:
IteratorType Current;
ptrdiff Length;
FIteratorType Current;
ptrdiff Length;
# if DO_CHECK
ptrdiff MaxLength;

View File

@ -24,7 +24,7 @@ struct IForwardIterator /* : IInputIterator<T>, IIncrementable, ISentinelFor<IFo
{
// ~Begin CInputIterator.
using ElementType = TRemoveCVRef<T>;
using FElementType = TRemoveCVRef<T>;
// ~End CInputIterator.

View File

@ -140,7 +140,7 @@ NODISCARD FORCEINLINE constexpr auto MakeBackInserter(C& Container)
/** Creates an iterator adapter inserted in the container. */
template <typename C>
NODISCARD FORCEINLINE constexpr auto MakeInserter(C& Container, const typename C::ConstIterator& InIter)
NODISCARD FORCEINLINE constexpr auto MakeInserter(C& Container, const typename C::FConstIterator& InIter)
{
return NAMESPACE_PRIVATE::TInsertIterator([&Container, Iter = InIter]<typename T>(T&& A) mutable { Iter = Container.Insert(Iter, Forward<T>(A)); });
}

View File

@ -26,9 +26,9 @@ class TMoveIterator final
{
public:
using IteratorType = I;
using FIteratorType = I;
using ElementType = TIteratorElement<I>;
using FElementType = TIteratorElement<I>;
FORCEINLINE constexpr TMoveIterator() requires (CDefaultConstructible<I>) = default;
@ -38,7 +38,7 @@ public:
FORCEINLINE constexpr TMoveIterator& operator=(TMoveIterator&&) = default;
FORCEINLINE constexpr ~TMoveIterator() = default;
FORCEINLINE constexpr explicit TMoveIterator(IteratorType InValue) : Current(MoveTemp(InValue)) { }
FORCEINLINE constexpr explicit TMoveIterator(FIteratorType InValue) : Current(MoveTemp(InValue)) { }
template <CInputIterator J> requires (!CSameAs<I, J> && CConstructibleFrom<I, const J&>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, I>) TMoveIterator(const TReverseIterator<J>& InValue) : Current(InValue.GetBase()) { }
@ -73,12 +73,12 @@ public:
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& LHS, const TMoveIterator& RHS) requires (CSizedSentinelFor<I, I>) { return LHS.GetBase() - RHS.GetBase(); }
NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; }
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); }
NODISCARD FORCEINLINE constexpr const FIteratorType& GetBase() const& { return Current; }
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { return MoveTemp(Current); }
private:
IteratorType Current;
FIteratorType Current;
};
@ -100,7 +100,7 @@ class TMoveSentinel
{
public:
using SentinelType = S;
using FSentinelType = S;
FORCEINLINE constexpr TMoveSentinel() = default;
FORCEINLINE constexpr TMoveSentinel(const TMoveSentinel&) = default;
@ -109,7 +109,7 @@ public:
FORCEINLINE constexpr TMoveSentinel& operator=(TMoveSentinel&&) = default;
FORCEINLINE constexpr ~TMoveSentinel() = default;
FORCEINLINE constexpr explicit TMoveSentinel(SentinelType InValue) : Last(InValue) { }
FORCEINLINE constexpr explicit TMoveSentinel(FSentinelType InValue) : Last(InValue) { }
template <CSemiregular T> requires (!CSameAs<S, T> && CConstructibleFrom<S, const T&>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const T&, S>) TMoveSentinel(const TMoveSentinel<T>& InValue) : Last(InValue.Last) { }
@ -126,12 +126,12 @@ public:
template <CInputIterator I> requires (CSizedSentinelFor<S, I>)
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator<I>& Iter, const TMoveSentinel& Sentinel) { return Iter.GetBase() - Sentinel.GetBase(); }
NODISCARD FORCEINLINE constexpr const SentinelType& GetBase() const& { return Last; }
NODISCARD FORCEINLINE constexpr SentinelType GetBase() && { return MoveTemp(Last); }
NODISCARD FORCEINLINE constexpr const FSentinelType& GetBase() const& { return Last; }
NODISCARD FORCEINLINE constexpr FSentinelType GetBase() && { return MoveTemp(Last); }
private:
SentinelType Last;
FSentinelType Last;
};

View File

@ -37,7 +37,7 @@ struct IRandomAccessIterator /* : IBidirectionalIterator<T>, ISizedSentinelFor<I
{
// ~Begin CBidirectionalIterator.
using ElementType = TRemoveCVRef<T>;
using FElementType = TRemoveCVRef<T>;
// ~End CBidirectionalIterator.

View File

@ -25,9 +25,9 @@ class TReverseIterator final
{
public:
using IteratorType = I;
using FIteratorType = I;
using ElementType = TIteratorElement<I>;
using FElementType = TIteratorElement<I>;
FORCEINLINE constexpr TReverseIterator() = default;
FORCEINLINE constexpr TReverseIterator(const TReverseIterator&) = default;
@ -36,7 +36,7 @@ public:
FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&&) = default;
FORCEINLINE constexpr ~TReverseIterator() = default;
FORCEINLINE constexpr explicit TReverseIterator(IteratorType InValue) : Current(InValue) { }
FORCEINLINE constexpr explicit TReverseIterator(FIteratorType InValue) : Current(InValue) { }
template <CBidirectionalIterator J> requires (!CSameAs<I, J> && CConstructibleFrom<I, const J&>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, I>) TReverseIterator(const TReverseIterator<J>& InValue) : Current(InValue.GetBase()) { }
@ -50,9 +50,9 @@ public:
template <CBidirectionalIterator J> requires (CThreeWayComparable<I, J>)
NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult<I, J> operator<=>(const TReverseIterator& LHS, const TReverseIterator<J>& RHS) { return RHS.GetBase() <=> LHS.GetBase(); }
NODISCARD FORCEINLINE constexpr TIteratorReference<I> operator*() const { IteratorType Temp = GetBase(); return *--Temp; }
NODISCARD FORCEINLINE constexpr TIteratorReference<I> operator*() const { FIteratorType Temp = GetBase(); return *--Temp; }
NODISCARD FORCEINLINE constexpr auto operator->() const requires (requires(const I Iter) { { ToAddress(Iter) } -> CSameAs<TIteratorPointer<I>>; }) { IteratorType Temp = GetBase(); return ToAddress(--Temp); }
NODISCARD FORCEINLINE constexpr auto operator->() const requires (requires(const I Iter) { { ToAddress(Iter) } -> CSameAs<TIteratorPointer<I>>; }) { FIteratorType Temp = GetBase(); return ToAddress(--Temp); }
NODISCARD FORCEINLINE constexpr TIteratorReference<I> operator[](ptrdiff Index) const requires (CRandomAccessIterator<I>) { return GetBase()[-Index - 1]; }
@ -72,12 +72,12 @@ public:
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CSizedSentinelFor<I, I>) { return RHS.GetBase() - LHS.GetBase(); }
NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; }
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); }
NODISCARD FORCEINLINE constexpr const FIteratorType& GetBase() const& { return Current; }
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { return MoveTemp(Current); }
private:
IteratorType Current;
FIteratorType Current;
};

View File

@ -12,17 +12,17 @@ NAMESPACE_PRIVATE_BEGIN
template <typename T> using TWithReference = T&;
template <typename I> struct TIteratorElementImpl { };
template <typename T> struct TIteratorElementImpl<T*> { using Type = TRemoveCV<T>; };
template <typename I> struct TIteratorElementImpl { };
template <typename T> struct TIteratorElementImpl<T*> { using FType = TRemoveCV<T>; };
template <typename I> requires (requires { typename I::ElementType; })
struct TIteratorElementImpl<I> { using Type = typename I::ElementType; };
template <typename I> requires (requires { typename I::FElementType; })
struct TIteratorElementImpl<I> { using FType = typename I::FElementType; };
template <typename I> struct TIteratorPointerImpl { };
template <typename T> struct TIteratorPointerImpl<T*> { using Type = T*; };
template <typename I> struct TIteratorPointerImpl { };
template <typename T> struct TIteratorPointerImpl<T*> { using FType = T*; };
template <typename I> requires (requires(I& Iter) { { Iter.operator->() } -> CPointer; })
struct TIteratorPointerImpl<I> { using Type = decltype(DeclVal<I&>().operator->()); };
struct TIteratorPointerImpl<I> { using FType = decltype(DeclVal<I&>().operator->()); };
NAMESPACE_PRIVATE_END
@ -33,10 +33,10 @@ template <typename T>
concept CDereferenceable = requires(T& A) { { *A } -> CReferenceable; };
template <typename I>
using TIteratorElement = typename NAMESPACE_PRIVATE::TIteratorElementImpl<TRemoveCVRef<I>>::Type;
using TIteratorElement = typename NAMESPACE_PRIVATE::TIteratorElementImpl<TRemoveCVRef<I>>::FType;
template <typename I>
using TIteratorPointer = typename NAMESPACE_PRIVATE::TIteratorPointerImpl<TRemoveCVRef<I>>::Type;
using TIteratorPointer = typename NAMESPACE_PRIVATE::TIteratorPointerImpl<TRemoveCVRef<I>>::FType;
template <CReferenceable I>
using TIteratorReference = decltype(*DeclVal<I&>());
@ -75,13 +75,13 @@ struct IIndirectlyReadable
* The element type of the indirectly readable type.
* It must be a non-const, non-volatile and non-reference type and can be referenced, i.e. not a void type.
*/
using ElementType = TRemoveCVRef<T>;
using FElementType = TRemoveCVRef<T>;
/**
* Indirectly read the element from the indirectly readable type.
* The return type may not be const ElementType&, this concept only requires that the return type
* and ElementType has some relationship, such as copy constructible to ElementType if the type is copyable.
* This means that returning a proxy class castable to ElementType is also valid.
* The return type may not be const FElementType&, this concept only requires that the return type
* and FElementType has some relationship, such as copy constructible to FElementType if the type is copyable.
* This means that returning a proxy class castable to FElementType is also valid.
* If this is an iterator adaptor, use decltype(auto) to forward the return value.
*/
T operator*() const;
@ -227,7 +227,7 @@ struct IInputIterator /* : IInputOrOutputIterator, IIndirectlyReadable */
{
// ~Begin CIndirectlyReadable.
using ElementType = TRemoveCVRef<T>;
using FElementType = TRemoveCVRef<T>;
// ~End CIndirectlyReadable.

View File

@ -17,7 +17,7 @@ concept CAllocatableObject = CObject<T> && !CConst<T> && !CVolatile<T> && CDestr
template <typename A, typename T = int>
concept CAllocator = !CSameAs<A, FAllocatorInterface> && CAllocatableObject<T>
&& requires (typename A::template ForElementType<T>& Allocator, T* InPtr, size_t Num, size_t NumAllocated)
&& requires (typename A::template TForElementType<T>& Allocator, T* InPtr, size_t Num, size_t NumAllocated)
{
{ Allocator.Allocate(Num) } -> CSameAs<T*>;
{ Allocator.Deallocate(InPtr) } -> CSameAs<void>;
@ -47,15 +47,15 @@ struct FAllocatorInterface
static constexpr bool bSupportsMultipleAllocation = true;
template <CAllocatableObject T>
class ForElementType /*: private FSingleton*/
class TForElementType /*: private FSingleton*/
{
public:
ForElementType() = default;
ForElementType(const ForElementType&) = delete;
ForElementType(ForElementType&&) = delete;
ForElementType& operator=(const ForElementType&) = delete;
ForElementType& operator=(ForElementType&&) = delete;
TForElementType() = default;
TForElementType(const TForElementType&) = delete;
TForElementType(TForElementType&&) = delete;
TForElementType& operator=(const TForElementType&) = delete;
TForElementType& operator=(TForElementType&&) = delete;
/** Allocates uninitialized storage. If 'InNum' is zero, return nullptr. */
NODISCARD FORCEINLINE T* Allocate(size_t InNum) = delete;
@ -110,7 +110,7 @@ struct FAllocatorInterface
\
}; \
\
PREPROCESSOR_JOIN(T, Name)<typename Allocator::template ForElementType<Type>> Name;
PREPROCESSOR_JOIN(T, Name)<typename Allocator::template TForElementType<Type>> Name;
/** This is heap allocator that calls Memory::Malloc() directly for memory allocation. */
struct FHeapAllocator
@ -118,15 +118,15 @@ struct FHeapAllocator
static constexpr bool bSupportsMultipleAllocation = true;
template <CAllocatableObject T>
class ForElementType /*: private FSingleton*/
class TForElementType /*: private FSingleton*/
{
public:
ForElementType() = default;
ForElementType(const ForElementType&) = delete;
ForElementType(ForElementType&&) = delete;
ForElementType& operator=(const ForElementType&) = delete;
ForElementType& operator=(ForElementType&&) = delete;
TForElementType() = default;
TForElementType(const TForElementType&) = delete;
TForElementType(TForElementType&&) = delete;
TForElementType& operator=(const TForElementType&) = delete;
TForElementType& operator=(TForElementType&&) = delete;
NODISCARD FORCEINLINE T* Allocate(size_t InNum)
{
@ -197,15 +197,15 @@ struct TInlineAllocator
static constexpr bool bSupportsMultipleAllocation = false;
template <CAllocatableObject T>
class ForElementType /*: private FSingleton*/
class TForElementType /*: private FSingleton*/
{
public:
ForElementType() = default;
ForElementType(const ForElementType&) = delete;
ForElementType(ForElementType&&) = delete;
ForElementType& operator=(const ForElementType&) = delete;
ForElementType& operator=(ForElementType&&) = delete;
TForElementType() = default;
TForElementType(const TForElementType&) = delete;
TForElementType(TForElementType&&) = delete;
TForElementType& operator=(const TForElementType&) = delete;
TForElementType& operator=(TForElementType&&) = delete;
NODISCARD FORCEINLINE T* Allocate(size_t InNum)
{
@ -279,15 +279,15 @@ struct FNullAllocator
static constexpr bool bSupportsMultipleAllocation = true;
template <CAllocatableObject T>
class ForElementType /*: private FSingleton*/
class TForElementType /*: private FSingleton*/
{
public:
ForElementType() = default;
ForElementType(const ForElementType&) = delete;
ForElementType(ForElementType&&) = delete;
ForElementType& operator=(const ForElementType&) = delete;
ForElementType& operator=(ForElementType&&) = delete;
TForElementType() = default;
TForElementType(const TForElementType&) = delete;
TForElementType(TForElementType&&) = delete;
TForElementType& operator=(const TForElementType&) = delete;
TForElementType& operator=(TForElementType&&) = delete;
NODISCARD FORCEINLINE T* Allocate(size_t InNum) { check_no_entry(); return nullptr; }

View File

@ -14,7 +14,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_PRIVATE_BEGIN
template <typename RT, typename ST>
using TRawPointer = TConditional<CVoid<RT>, typename TPointerTraits<TRemoveCVRef<ST>>::ElementType*, RT>;
using TRawPointer = TConditional<CVoid<RT>, typename TPointerTraits<TRemoveCVRef<ST>>::FElementType*, RT>;
template <bool bEnableInput, typename RT, typename ST, typename... Ts>
class FInOutPtr final : private FSingleton
@ -57,7 +57,7 @@ NAMESPACE_PRIVATE_END
template <typename RT = void, typename ST, typename... Ts> requires ((CVoid<RT>) || (CPointer<RT>)
&& (requires(NAMESPACE_PRIVATE::TRawPointer<RT, ST>* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward<Ts>(Args)...); })
|| (CConstructibleFrom<ST, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, Ts...> && CMoveAssignable<ST>)
&& requires { typename TPointerTraits<TRemoveCV<ST>>::ElementType; })
&& requires { typename TPointerTraits<TRemoveCV<ST>>::FElementType; })
auto OutPtr(ST& InPtr, Ts&&... Args)
{
return NAMESPACE_PRIVATE::FInOutPtr<false, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, ST, Ts...>(InPtr, Forward<Ts>(Args)...);
@ -67,7 +67,7 @@ template <typename RT = void, typename ST, typename... Ts> requires ((CVoid<RT>)
&& (requires(NAMESPACE_PRIVATE::TRawPointer<RT, ST>* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward<Ts>(Args)...); })
|| (CConstructibleFrom<ST, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, Ts...> && CMoveAssignable<ST>)
&& requires(ST& SPtr) { { SPtr.Release() } -> CConvertibleTo<NAMESPACE_PRIVATE::TRawPointer<RT, ST>>; }
&& requires { typename TPointerTraits<TRemoveCV<ST>>::ElementType; })
&& requires { typename TPointerTraits<TRemoveCV<ST>>::FElementType; })
auto InOutPtr(ST& InPtr, Ts&&... Args)
{
return NAMESPACE_PRIVATE::FInOutPtr<true, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, ST, Ts...>(InPtr, Forward<Ts>(Args)...);

View File

@ -19,10 +19,10 @@ struct TPointerTraits<T*>
{
static constexpr bool bIsPointer = true;
using PointerType = T*;
using ElementType = T;
using FPointerType = T*;
using FElementType = T;
static FORCEINLINE constexpr ElementType* ToAddress(PointerType InPtr)
static FORCEINLINE constexpr FElementType* ToAddress(FPointerType InPtr)
{
return InPtr;
}
@ -34,29 +34,29 @@ struct TPointerTraits<T(*)[]>
{
static constexpr bool bIsPointer = true;
using PointerType = T(*)[];
using ElementType = T;
using FPointerType = T(*)[];
using FElementType = T;
static FORCEINLINE constexpr ElementType* ToAddress(PointerType InPtr)
static FORCEINLINE constexpr FElementType* ToAddress(FPointerType InPtr)
{
return InPtr;
}
};
/** A specialization of TPointerTraits is provided for pointer-like type. */
#define DEFINE_TPointerTraits(TPtr) \
template <typename T> \
struct TPointerTraits<TPtr<T>> \
{ \
static constexpr bool bIsPointer = true; \
\
using PointerType = TPtr<T>; \
using ElementType = TPtr<T>::ElementType; \
\
static FORCEINLINE constexpr ElementType* ToAddress(const PointerType& InPtr) \
{ \
return InPtr.Get(); \
} \
#define DEFINE_TPointerTraits(TPtr) \
template <typename T> \
struct TPointerTraits<TPtr<T>> \
{ \
static constexpr bool bIsPointer = true; \
\
using FPointerType = TPtr<T>; \
using FElementType = TPtr<T>::FElementType; \
\
static FORCEINLINE constexpr FElementType* ToAddress(const FPointerType& InPtr) \
{ \
return InPtr.Get(); \
} \
};
NAMESPACE_MODULE_END(Utility)

View File

@ -58,18 +58,18 @@ class alignas(Memory::ConstructiveInterference) FSharedController : private FSin
{
private:
using RefCounter = TAtomic<size_t>;
using FRefCounter = TAtomic<size_t>;
// Ensure that counters are lock-free for performance.
static_assert(RefCounter::bIsAlwaysLockFree);
static_assert(FRefCounter::bIsAlwaysLockFree);
// When this count is zero the object is destroyed.
// This count is the number of TSharedRef and TSharedPtr.
RefCounter SharedReferenceCount;
FRefCounter SharedReferenceCount;
// When this count is zero the controller is destroyed.
// If SharedCounter is not zero this count is one more than the number of TWeakPtr.
RefCounter WeakReferenceCount;
FRefCounter WeakReferenceCount;
public:
@ -86,7 +86,7 @@ public:
virtual void DestroyThis() { delete this; }
// Get shared reference count, no definite operation order.
FORCEINLINE RefCounter::ValueType GetSharedReferenceCount()
FORCEINLINE FRefCounter::FValueType GetSharedReferenceCount()
{
// Get the shared reference count as EMemoryOrder::Relaxed,
// since this count is for reference only and has no guarantees,
@ -109,7 +109,7 @@ public:
// if the shared reference count is zero return false.
bool AddSharedReferenceIfUnexpired()
{
RefCounter::ValueType OldSharedReferenceCount = GetSharedReferenceCount();
FRefCounter::FValueType OldSharedReferenceCount = GetSharedReferenceCount();
// We need to make sure we don't increase the reference count from zero to one.
while (true)
@ -131,7 +131,7 @@ public:
// where EMemoryOrder::Release ensures that the side effects of all operations
// on the shared reference count of all threads are visible to this thread,
// preventing the shared reference count from actually going to zero.
RefCounter::ValueType OldSharedReferenceCount = SharedReferenceCount.FetchSub(1, EMemoryOrder::Release);
FRefCounter::FValueType OldSharedReferenceCount = SharedReferenceCount.FetchSub(1, EMemoryOrder::Release);
// Make sure the shared reference count is not zero before.
check(OldSharedReferenceCount != 0);
@ -166,7 +166,7 @@ public:
{
// The use of EMemoryOrder is the same as in ReleaseSharedReference().
RefCounter::ValueType OldWeakReferenceCount = WeakReferenceCount.FetchSub(1, EMemoryOrder::Release);
FRefCounter::FValueType OldWeakReferenceCount = WeakReferenceCount.FetchSub(1, EMemoryOrder::Release);
check(OldWeakReferenceCount != 0);
@ -407,12 +407,12 @@ struct FSharedHelper
if constexpr (CTWeakPtr<T> && CTWeakPtr<U>)
{
if (&InValue == &This) UNLIKELY return This;
if (This.Controller != nullptr)
{
This.Controller->ReleaseWeakReference();
}
This.Pointer = Exchange(InValue.Pointer, nullptr);
This.Controller = Exchange(InValue.Controller, nullptr);
}
@ -522,7 +522,7 @@ protected:
private:
using SharedFromThisType = TSharedFromThis;
using FSharedFromThisType = TSharedFromThis;
// Here it is updated by the private constructor of TSharedRef or TSharedPtr.
mutable TWeakPtr<T> WeakThis;
@ -539,12 +539,12 @@ class TSharedRef final
{
private:
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
public:
using ElementType = T;
using WeakType = TWeakPtr<T>;
using FElementType = T;
using FWeakType = TWeakPtr<T>;
/** TSharedRef cannot be initialized by nullptr. */
TSharedRef() = delete;
@ -580,7 +580,7 @@ public:
Controller->AddSharedReference();
}
/**
* Aliasing constructor used to create a shared reference which shares its reference count with
* another shared object, but pointing to a different object, typically a subobject.
@ -610,18 +610,18 @@ public:
FORCEINLINE ~TSharedRef() { Controller->ReleaseSharedReference(); }
/** Replaces the managed object with the one managed by 'InValue'. */
FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return Helper::CopySharedReference(*this, InValue); }
FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return FHelper::CopySharedReference(*this, InValue); }
/** Replaces the managed object with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE TSharedRef& operator=(const TSharedRef<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
FORCEINLINE TSharedRef& operator=(const TSharedRef<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
/** Replaces the managed object with the one managed by 'InValue'. */
FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
/** Replaces the managed object with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
/** Compares the pointer values of two TSharedRef. */
template <typename U> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
@ -732,15 +732,15 @@ private:
{
check(!((Pointer == nullptr) ^ (Controller == nullptr)));
if constexpr (CClass<T> && !CVolatile<T> && requires { typename T::SharedFromThisType; })
if constexpr (CClass<T> && !CVolatile<T> && requires { typename T::FSharedFromThisType; })
{
using SharedFromThisType = T::SharedFromThisType;
using FSharedFromThisType = typename T::FSharedFromThisType;
if constexpr (CDerivedFrom<T, SharedFromThisType>)
if constexpr (CDerivedFrom<T, FSharedFromThisType>)
{
if (Pointer != nullptr)
{
const SharedFromThisType& SharedFromThis = *Pointer;
const FSharedFromThisType& SharedFromThis = *Pointer;
checkf(!SharedFromThis.DoesSharedInstanceExist(), TEXT("This object is incorrectly managed by multiple TSharedRef or TSharedPtr."));
SharedFromThis.WeakThis = ConstCast<TRemoveCV<T>>(*this);
}
@ -762,12 +762,12 @@ class TSharedRef<T[]> final
{
private:
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
public:
using ElementType = T;
using WeakType = TWeakPtr<T>;
using FElementType = T;
using FWeakType = TWeakPtr<T>;
/** TSharedRef cannot be initialized by nullptr. */
TSharedRef() = delete;
@ -835,18 +835,18 @@ public:
FORCEINLINE ~TSharedRef() { Controller->ReleaseSharedReference(); }
/** Replaces the managed array with the one managed by 'InValue'. */
FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return Helper::CopySharedReference(*this, InValue); }
FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return FHelper::CopySharedReference(*this, InValue); }
/** Replaces the managed array with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
FORCEINLINE TSharedRef& operator=(const TSharedRef<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
FORCEINLINE TSharedRef& operator=(const TSharedRef<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
/** Replaces the managed array with the one managed by 'InValue'. */
FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
/** Replaces the managed array with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
/** Compares the pointer values of two TSharedRef. */
template <typename U> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
@ -972,13 +972,13 @@ class TSharedPtr final
{
private:
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
public:
using ElementType = T;
using WeakType = TWeakPtr<T>;
using FElementType = T;
using FWeakType = TWeakPtr<T>;
/** Constructs an empty shared pointer. */
FORCEINLINE constexpr TSharedPtr() : Pointer(nullptr), Controller(nullptr) { }
@ -1073,22 +1073,22 @@ public:
FORCEINLINE ~TSharedPtr() { if (Controller != nullptr) Controller->ReleaseSharedReference(); }
/** Replaces the managed object with the one managed by 'InValue'. */
FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return Helper::CopySharedReference(*this, InValue); }
FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return FHelper::CopySharedReference(*this, InValue); }
/** Replaces the managed object with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE TSharedPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
FORCEINLINE TSharedPtr& operator=(const TSharedPtr<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
/** Replaces the managed object with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE TSharedPtr& operator=(const TSharedRef<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
FORCEINLINE TSharedPtr& operator=(const TSharedRef<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
/** Replaces the managed object with the one managed by 'InValue'. */
FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
/** Replaces the managed object with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE TSharedPtr& operator=(TSharedPtr<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
FORCEINLINE TSharedPtr& operator=(TSharedPtr<U>&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
/** Replaces the managed object with the one managed by 'InValue'. */
template <typename U, typename E> requires (CConvertibleTo<U*, T*> && !CArray<U> && (CDestructible<E> || CLValueReference<E>))
@ -1200,14 +1200,14 @@ private:
T* Pointer;
NAMESPACE_PRIVATE::FSharedController* Controller;
FORCEINLINE TSharedPtr(const TWeakPtr<T>& InValue)
{
const bool bIsUnexpired = InValue.Controller != nullptr && InValue.Controller->AddSharedReferenceIfUnexpired();
Pointer = bIsUnexpired ? InValue.Pointer : nullptr;
Controller = bIsUnexpired ? InValue.Controller : nullptr;
}
FORCEINLINE TSharedPtr(T* InPtr, NAMESPACE_PRIVATE::FSharedController* InController)
@ -1215,15 +1215,15 @@ private:
{
check(!((Pointer == nullptr) ^ (Controller == nullptr)));
if constexpr (CClass<T> && !CVolatile<T> && requires { typename T::SharedFromThisType; })
if constexpr (CClass<T> && !CVolatile<T> && requires { typename T::FSharedFromThisType; })
{
using SharedFromThisType = T::SharedFromThisType;
using FSharedFromThisType = typename T::FSharedFromThisType;
if constexpr (CDerivedFrom<T, SharedFromThisType>)
if constexpr (CDerivedFrom<T, FSharedFromThisType>)
{
if (Pointer != nullptr)
{
const SharedFromThisType& SharedFromThis = *Pointer;
const FSharedFromThisType& SharedFromThis = *Pointer;
checkf(!SharedFromThis.DoesSharedInstanceExist(), TEXT("This object is incorrectly managed by multiple TSharedRef or TSharedPtr."));
SharedFromThis.WeakThis = ConstCast<TRemoveCV<T>>(*this);
}
@ -1245,12 +1245,12 @@ class TSharedPtr<T[]> final
{
private:
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
public:
using ElementType = T;
using WeakType = TWeakPtr<T>;
using FElementType = T;
using FWeakType = TWeakPtr<T>;
/** Constructs an empty shared pointer. */
FORCEINLINE constexpr TSharedPtr() : Pointer(nullptr), Controller(nullptr) { }
@ -1348,22 +1348,22 @@ public:
FORCEINLINE ~TSharedPtr() { if (Controller != nullptr) Controller->ReleaseSharedReference(); }
/** Replaces the managed array with the one managed by 'InValue'. */
FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return Helper::CopySharedReference(*this, InValue); }
FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return FHelper::CopySharedReference(*this, InValue); }
/** Replaces the managed array with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
FORCEINLINE TSharedPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
FORCEINLINE TSharedPtr& operator=(const TSharedPtr<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
/** Replaces the managed array with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
FORCEINLINE TSharedPtr& operator=(const TSharedRef<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
FORCEINLINE TSharedPtr& operator=(const TSharedRef<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
/** Replaces the managed array with the one managed by 'InValue'. */
FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
/** Replaces the managed array with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
FORCEINLINE TSharedPtr& operator=(TSharedPtr<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
FORCEINLINE TSharedPtr& operator=(TSharedPtr<U>&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
/** Replaces the managed array with the one managed by 'InValue'. */
template <typename U, typename E> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U> && (CDestructible<E> || CLValueReference<E>))
@ -1482,7 +1482,7 @@ private:
Pointer = bIsUnexpired ? InValue.Pointer : nullptr;
Controller = bIsUnexpired ? InValue.Controller : nullptr;
}
FORCEINLINE TSharedPtr(T* InPtr, NAMESPACE_PRIVATE::FSharedController* InController)
@ -1505,11 +1505,11 @@ class TWeakPtr final
{
private:
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
public:
using ElementType = T;
using FElementType = T;
/** Constructs an empty TWeakPtr */
FORCEINLINE constexpr TWeakPtr() : Pointer(nullptr), Controller(nullptr) { }
@ -1542,7 +1542,7 @@ public:
/** Move constructors. Moves a TWeakPtr instance from 'InValue' into this. */
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE constexpr TWeakPtr(TWeakPtr<U>&& InValue) : Pointer(Exchange(InValue.Pointer, nullptr)), Controller(Exchange(InValue.Controller, nullptr)) { }
/** Constructs a weak pointer from a shared reference. */
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE constexpr TWeakPtr(const TSharedRef<U>& InValue) : Pointer(InValue.Pointer), Controller(InValue.Controller)
@ -1564,26 +1564,26 @@ public:
FORCEINLINE ~TWeakPtr() { if (Controller != nullptr) Controller->ReleaseWeakReference(); }
/** Replaces the managed object with the one managed by 'InValue'. */
FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return Helper::CopyWeakReference(*this, InValue); }
FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
/** Replaces the managed object with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE TWeakPtr& operator=(const TWeakPtr<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
FORCEINLINE TWeakPtr& operator=(const TWeakPtr<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
/** Replaces the managed object with the one managed by 'InValue'. */
FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); }
FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return FHelper::MoveWeakReference(*this, MoveTemp(InValue)); }
/** Replaces the managed object with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE TWeakPtr& operator=(TWeakPtr<U>&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); }
FORCEINLINE TWeakPtr& operator=(TWeakPtr<U>&& InValue) { return FHelper::MoveWeakReference(*this, MoveTemp(InValue)); }
/** Assignment operator sets this weak pointer from a shared reference. */
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE TWeakPtr& operator=(const TSharedRef<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
FORCEINLINE TWeakPtr& operator=(const TSharedRef<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
/** Assignment operator sets this weak pointer from a shared pointer. */
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE TWeakPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
FORCEINLINE TWeakPtr& operator=(const TSharedPtr<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
/** Effectively the same as calling Reset(). */
FORCEINLINE TWeakPtr& operator=(nullptr_t) { Reset(); return *this; }
@ -1639,11 +1639,11 @@ class TWeakPtr<T[]> final
{
private:
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
public:
using ElementType = T;
using FElementType = T;
/** Constructs an empty TWeakPtr */
FORCEINLINE constexpr TWeakPtr() : Pointer(nullptr), Controller(nullptr) { }
@ -1698,26 +1698,26 @@ public:
FORCEINLINE ~TWeakPtr() { if (Controller != nullptr) Controller->ReleaseWeakReference(); }
/** Replaces the managed array with the one managed by 'InValue'. */
FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return Helper::CopyWeakReference(*this, InValue); }
FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
/** Replaces the managed array with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
FORCEINLINE TWeakPtr& operator=(const TWeakPtr<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
FORCEINLINE TWeakPtr& operator=(const TWeakPtr<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
/** Replaces the managed array with the one managed by 'InValue'. */
FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); }
FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return FHelper::MoveWeakReference(*this, MoveTemp(InValue)); }
/** Replaces the managed array with the one managed by 'InValue'. */
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
FORCEINLINE TWeakPtr& operator=(TWeakPtr<U>&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); }
FORCEINLINE TWeakPtr& operator=(TWeakPtr<U>&& InValue) { return FHelper::MoveWeakReference(*this, MoveTemp(InValue)); }
/** Assignment operator sets this weak pointer from a shared reference. */
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
FORCEINLINE TWeakPtr& operator=(const TSharedRef<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
FORCEINLINE TWeakPtr& operator=(const TSharedRef<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
/** Assignment operator sets this weak pointer from a shared pointer. */
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
FORCEINLINE TWeakPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
FORCEINLINE TWeakPtr& operator=(const TSharedPtr<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
/** Effectively the same as calling Reset(). */
FORCEINLINE TWeakPtr& operator=(nullptr_t) { Reset(); return *this; }

View File

@ -179,8 +179,8 @@ class TUniqueRef final : private FSingleton
{
public:
using ElementType = T;
using DeleterType = E;
using FElementType = T;
using FDeleterType = E;
/** TUniqueRef cannot be initialized by nullptr. */
TUniqueRef() = delete;
@ -308,8 +308,8 @@ class TUniqueRef<T[], E> final : private FSingleton
{
public:
using ElementType = T;
using DeleterType = E;
using FElementType = T;
using FDeleterType = E;
/** TUniqueRef cannot be initialized by nullptr. */
TUniqueRef() = delete;
@ -439,8 +439,8 @@ class TUniquePtr final : private FNoncopyable
{
public:
using ElementType = T;
using DeleterType = E;
using FElementType = T;
using FDeleterType = E;
/** Constructs a TUniquePtr that owns nothing. Value-initializes the stored pointer and the stored deleter. */
FORCEINLINE constexpr TUniquePtr() requires(CDefaultConstructible<E> && !CPointer<E>) : Storage(nullptr) { }
@ -585,8 +585,8 @@ class TUniquePtr<T[], E> final : private FNoncopyable
{
public:
using ElementType = T;
using DeleterType = E;
using FElementType = T;
using FDeleterType = E;
/** Constructs a TUniquePtr that owns nothing. Value-initializes the stored pointer and the stored deleter. */
FORCEINLINE constexpr TUniquePtr() requires(CDefaultConstructible<E> && !CPointer<E>) : Storage(nullptr) { }

View File

@ -42,6 +42,8 @@ NAMESPACE_PRIVATE_END
# define DO_CHECK 0
#endif
// ReSharper disable CppInconsistentNaming
#define always_check(InExpr) RS_CHECK_IMPL(InExpr)
#define always_checkf(InExpr, InFormat, ...) RS_CHECK_F_IMPL(InExpr, InFormat, ##__VA_ARGS__)
#define always_check_no_entry() always_checkf(false, "Enclosing block should never be called.")
@ -77,6 +79,8 @@ NAMESPACE_PRIVATE_END
#endif
// ReSharper restore CppInconsistentNaming
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -12,17 +12,21 @@ NAMESPACE_MODULE_BEGIN(Utility)
// The result of the three-way comparison operator is the built-in type of the compiler, which is directly introduced here
typedef NAMESPACE_STD::partial_ordering partial_ordering;
typedef NAMESPACE_STD::weak_ordering weak_ordering;
typedef NAMESPACE_STD::strong_ordering strong_ordering;
// ReSharper disable CppInconsistentNaming
using partial_ordering = NAMESPACE_STD::partial_ordering;
using weak_ordering = NAMESPACE_STD::weak_ordering;
using strong_ordering = NAMESPACE_STD::strong_ordering;
// ReSharper restore CppInconsistentNaming
NAMESPACE_PRIVATE_BEGIN
template<int32> struct TCommonComparisonCategoryBasic { };
template<> struct TCommonComparisonCategoryBasic<0> { using Type = strong_ordering; };
template<> struct TCommonComparisonCategoryBasic<2> { using Type = partial_ordering; };
template<> struct TCommonComparisonCategoryBasic<4> { using Type = weak_ordering; };
template<> struct TCommonComparisonCategoryBasic<6> { using Type = partial_ordering; };
template<int32> struct TCommonComparisonCategoryBasic { };
template<> struct TCommonComparisonCategoryBasic<0> { using FType = strong_ordering; };
template<> struct TCommonComparisonCategoryBasic<2> { using FType = partial_ordering; };
template<> struct TCommonComparisonCategoryBasic<4> { using FType = weak_ordering; };
template<> struct TCommonComparisonCategoryBasic<6> { using FType = partial_ordering; };
template <typename... Ts>
struct TCommonComparisonCategoryImpl
@ -32,13 +36,13 @@ struct TCommonComparisonCategoryImpl
CSameAs<Ts, weak_ordering > ? 4u :
CSameAs<Ts, partial_ordering> ? 2u : 1u
)
)>
)>
{ };
NAMESPACE_PRIVATE_END
template <typename... Ts>
using TCommonComparisonCategory = typename NAMESPACE_PRIVATE::TCommonComparisonCategoryImpl<Ts...>::Type;
using TCommonComparisonCategory = typename NAMESPACE_PRIVATE::TCommonComparisonCategoryImpl<Ts...>::FType;
template <typename T, typename OrderingType>
concept CThreeWayComparesAs = CSameAs<TCommonComparisonCategory<T, OrderingType>, OrderingType>;

View File

@ -17,7 +17,7 @@ class TConstantIterator final
{
public:
using ElementType = TRemoveCV<T>;
using FElementType = TRemoveCV<T>;
FORCEINLINE constexpr TConstantIterator() = default;
@ -70,7 +70,7 @@ class TConstantIterator<T&> final
{
public:
using ElementType = TRemoveCV<T>;
using FElementType = TRemoveCV<T>;
FORCEINLINE constexpr TConstantIterator() = default;
@ -115,14 +115,14 @@ class TCountedIterator<TConstantIterator<T>> final
{
public:
using IteratorType = TConstantIterator<T>;
using FIteratorType = TConstantIterator<T>;
using ElementType = typename TConstantIterator<T>::ElementType;
using FElementType = typename TConstantIterator<T>::FElementType;
# if DO_CHECK
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<IteratorType>) : Length(1), MaxLength(0) { }
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<FIteratorType>) : Length(1), MaxLength(0) { }
# else
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<IteratorType>) = default;
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<FIteratorType>) = default;
# endif
FORCEINLINE constexpr TCountedIterator(const TCountedIterator&) = default;
@ -132,25 +132,25 @@ public:
FORCEINLINE constexpr ~TCountedIterator() = default;
template <typename U = IteratorType> requires (!CSameAs<TCountedIterator, TRemoveCVRef<U>> && CConstructibleFrom<IteratorType, U>)
template <typename U = FIteratorType> requires (!CSameAs<TCountedIterator, TRemoveCVRef<U>> && CConstructibleFrom<FIteratorType, U>)
FORCEINLINE constexpr explicit TCountedIterator(U&& InValue, ptrdiff N) : Current(Forward<U>(InValue)), Length(N) { check_code({ MaxLength = N; }); }
template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConstructibleFrom<IteratorType, const J&>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, IteratorType>) TCountedIterator(const TCountedIterator<J>& InValue) : Current(InValue.Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConstructibleFrom<FIteratorType, const J&>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, FIteratorType>) TCountedIterator(const TCountedIterator<J>& InValue) : Current(InValue.Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConstructibleFrom<IteratorType, J>)
FORCEINLINE constexpr explicit (!CConvertibleTo<J&&, IteratorType>) TCountedIterator(TCountedIterator<J>&& InValue) : Current(MoveTemp(InValue).Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConstructibleFrom<FIteratorType, J>)
FORCEINLINE constexpr explicit (!CConvertibleTo<J&&, FIteratorType>) TCountedIterator(TCountedIterator<J>&& InValue) : Current(MoveTemp(InValue).Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConvertibleTo<const J&, IteratorType> && CAssignableFrom<IteratorType&, const J&>)
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConvertibleTo<const J&, FIteratorType> && CAssignableFrom<FIteratorType&, const J&>)
FORCEINLINE constexpr TCountedIterator& operator=(const TCountedIterator<J>& InValue) { Current = InValue.Current; Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; }
template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConvertibleTo<J&&, IteratorType> && CAssignableFrom<IteratorType&, J&&>)
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConvertibleTo<J&&, FIteratorType> && CAssignableFrom<FIteratorType&, J&&>)
FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator<J>&& InValue) { Current = MoveTemp(InValue).Current; Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; }
template <CCommonType<IteratorType> J>
template <CCommonType<FIteratorType> J>
NODISCARD friend FORCEINLINE constexpr bool operator==(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { return LHS.Length == RHS.Length; }
template <CCommonType<IteratorType> J>
template <CCommonType<FIteratorType> J>
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { return LHS.Length <=> RHS.Length; }
NODISCARD FORCEINLINE constexpr bool operator==(FDefaultSentinel) const& { return Length == static_cast<ptrdiff>(0); }
@ -176,20 +176,20 @@ public:
NODISCARD FORCEINLINE constexpr TCountedIterator operator-(ptrdiff Offset) const { TCountedIterator Temp = *this; Temp -= Offset; return Temp; }
template <CCommonType<IteratorType> J>
template <CCommonType<FIteratorType> J>
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Length - RHS.Length; }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { LHS.CheckThis(); return -LHS.Num(); }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { RHS.CheckThis(); return RHS.Num(); }
NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { CheckThis(); return Current; }
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { CheckThis(); return MoveTemp(Current); }
NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; }
NODISCARD FORCEINLINE constexpr const FIteratorType& GetBase() const& { CheckThis(); return Current; }
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { CheckThis(); return MoveTemp(Current); }
NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; }
private:
IteratorType Current;
ptrdiff Length;
FIteratorType Current;
ptrdiff Length;
# if DO_CHECK
ptrdiff MaxLength;

View File

@ -9,6 +9,8 @@ NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
// ReSharper disable CppInconsistentNaming
#define NORETURN [[noreturn]]
#define CARRIES_DEPENDENCY [[carries_dependency]]
#define DEPRECATED(Message) [[deprecated(Message)]]
@ -42,6 +44,8 @@ using type_info = NAMESPACE_STD::type_info;
template <typename T>
using initializer_list = NAMESPACE_STD::initializer_list<T>;
// ReSharper restore CppInconsistentNaming
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -14,6 +14,8 @@ NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
// ReSharper disable CppInconsistentNaming
// Platform information macro
#ifndef PLATFORM_NAME
@ -527,6 +529,8 @@ NAMESPACE_PRIVATE_END
#define U32TEXT(X) U32TEXT_PASTE(X)
#define UNICODETEXT(X) U32TEXT_PASTE(X)
// ReSharper restore CppInconsistentNaming
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -444,83 +444,83 @@ RESOLVE_ARITHMETIC_AMBIGUITY_2_ARGS(CArithmetic, IsNearlyZero)
template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr bool IsInfinity(T A)
{
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
return (IntegralValue & Traits::ExponentMask) == Traits::ExponentMask && (IntegralValue & Traits::MantissaMask) == 0;
return (IntegralValue & FTraits::ExponentMask) == FTraits::ExponentMask && (IntegralValue & FTraits::MantissaMask) == 0;
}
/** @return true if the given value is NaN, false otherwise. */
template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr bool IsNaN(T A)
{
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
return (IntegralValue & Traits::ExponentMask) == Traits::ExponentMask && (IntegralValue & Traits::MantissaMask) != 0;
return (IntegralValue & FTraits::ExponentMask) == FTraits::ExponentMask && (IntegralValue & FTraits::MantissaMask) != 0;
}
/** @return true if the given value is normal, false otherwise. */
template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr bool IsNormal(T A)
{
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
return (IntegralValue & Traits::ExponentMask) != 0 && (IntegralValue & Traits::ExponentMask) != Traits::ExponentMask;
return (IntegralValue & FTraits::ExponentMask) != 0 && (IntegralValue & FTraits::ExponentMask) != FTraits::ExponentMask;
}
/** @return true if the given value is subnormal, false otherwise. */
template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr bool IsDenorm(T A)
{
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
return (IntegralValue & Traits::ExponentMask) == 0 && (IntegralValue & Traits::MantissaMask) != 0;
return (IntegralValue & FTraits::ExponentMask) == 0 && (IntegralValue & FTraits::MantissaMask) != 0;
}
/** @return true if the given value is negative, even -0.0, false otherwise. */
template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr bool IsNegative(T A)
{
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
return (IntegralValue & Traits::SignMask) >> Traits::SignShift;
return (IntegralValue & FTraits::SignMask) >> FTraits::SignShift;
}
/** @return The exponent of the given value. */
template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr uint Exponent(T A)
{
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
return ((IntegralValue & Traits::ExponentMask) >> Traits::ExponentShift) - Traits::ExponentBias;
return ((IntegralValue & FTraits::ExponentMask) >> FTraits::ExponentShift) - FTraits::ExponentBias;
}
/** @return The NaN value with the given payload. */
template <CFloatingPoint T, CUnsignedIntegral U>
NODISCARD FORCEINLINE constexpr T NaN(U Payload)
{
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
checkf(Payload != 0, TEXT("Illegal payload. It must not be zero."));
checkf(Payload < (static_cast<typename Traits::FIntegralT>(1) << Traits::MantissaBits), TEXT("Illegal payload. It must be less than 2^MantissaBits."));
checkf(Payload < (static_cast<typename FTraits::FIntegralT>(1) << FTraits::MantissaBits), TEXT("Illegal payload. It must be less than 2^MantissaBits."));
if (Payload == 0) return TNumericLimits<T>::QuietNaN();
typename Traits::FIntegralT ValidPayload = Payload & Traits::MantissaMask;
typename FTraits::FIntegralT ValidPayload = Payload & FTraits::MantissaMask;
return Math::BitCast<T>(ValidPayload | Traits::ExponentMask);
return Math::BitCast<T>(ValidPayload | FTraits::ExponentMask);
}
/** @return The NaN value with the given payload. */
@ -536,11 +536,11 @@ NODISCARD FORCEINLINE constexpr T NaN(U Payload)
template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr auto NaNPayload(T A)
{
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
return IntegralValue & Traits::MantissaMask;
return IntegralValue & FTraits::MantissaMask;
}
/** @return The NaN payload of the given value. */

View File

@ -2,6 +2,7 @@
#include "CoreTypes.h"
#include "Range/View.h"
#include "Range/Pipe.h"
#include "Range/Utility.h"
#include "Templates/Utility.h"
#include "TypeTraits/TypeTraits.h"
@ -148,6 +149,15 @@ NODISCARD FORCEINLINE constexpr auto All(R&& InRange)
else return TOwningView(Forward<R>(InRange));
}
/** Creates A view adapter that includes all elements of a range. */
NODISCARD FORCEINLINE constexpr auto All()
{
return TAdaptorClosure([]<CViewableRange R> requires (requires { All(DeclVal<R&&>()); }) (R && Base)
{
return All(Forward<R>(Base));
});
}
/** A view adapter that includes all elements of a range. */
template <CViewableRange R>
using TAllView = decltype(Range::All(DeclVal<R>()));

View File

@ -19,18 +19,18 @@ class TEmptyView : public IBasicViewInterface<TEmptyView<T>>
{
public:
using ElementType = T;
using Reference = T&;
using Iterator = T*;
using Sentinel = T*;
using FElementType = T;
using FReference = T&;
using FIterator = T*;
using FSentinel = T*;
FORCEINLINE constexpr TEmptyView() = default;
NODISCARD static FORCEINLINE constexpr Iterator Begin() { return nullptr; }
NODISCARD static FORCEINLINE constexpr Sentinel End() { return nullptr; }
NODISCARD static FORCEINLINE constexpr T* GetData() { return nullptr; }
NODISCARD static FORCEINLINE constexpr size_t Num() { return 0; }
NODISCARD static FORCEINLINE constexpr bool IsEmpty() { return true; }
NODISCARD static FORCEINLINE constexpr FIterator Begin() { return nullptr; }
NODISCARD static FORCEINLINE constexpr FSentinel End() { return nullptr; }
NODISCARD static FORCEINLINE constexpr T* GetData() { return nullptr; }
NODISCARD static FORCEINLINE constexpr size_t Num() { return 0; }
NODISCARD static FORCEINLINE constexpr bool IsEmpty() { return true; }
};
@ -52,16 +52,16 @@ class TSingleView : public IBasicViewInterface<TSingleView<T>>
{
public:
using ElementType = T;
using FElementType = T;
using Reference = T&;
using ConstReference = const T&;
using FReference = T&;
using FConstReference = const T&;
using Iterator = T*;
using ConstIterator = const T*;
using FIterator = T*;
using FConstIterator = const T*;
using Sentinel = T*;
using ConstSentinel = const T*;
using FSentinel = T*;
using FConstSentinel = const T*;
FORCEINLINE constexpr TSingleView() requires (CDefaultConstructible<T>) = default;
@ -72,10 +72,10 @@ public:
template <typename... Ts> requires (CConstructibleFrom<T, Ts...>)
FORCEINLINE constexpr explicit TSingleView(FInPlace, Ts&&... Args) : Value(Forward<Ts>(Args)...) { }
FORCEINLINE constexpr Iterator Begin() { return GetData(); }
FORCEINLINE constexpr ConstIterator Begin() const { return GetData(); }
FORCEINLINE constexpr Sentinel End() { return GetData() + 1; }
FORCEINLINE constexpr ConstSentinel End() const { return GetData() + 1; }
FORCEINLINE constexpr FIterator Begin() { return GetData(); }
FORCEINLINE constexpr FConstIterator Begin() const { return GetData(); }
FORCEINLINE constexpr FSentinel End() { return GetData() + 1; }
FORCEINLINE constexpr FConstSentinel End() const { return GetData() + 1; }
NODISCARD FORCEINLINE constexpr T* GetData() { return AddressOf(Value); }
NODISCARD FORCEINLINE constexpr const T* GetData() const { return AddressOf(Value); }
@ -108,13 +108,13 @@ private:
public:
using ElementType = TRemoveCV<W>;
using FElementType = TRemoveCV<W>;
using Reference = W;
using FReference = W;
using Iterator = FIteratorImpl;
using FIterator = FIteratorImpl;
using Sentinel = TConditional<CSameAs<W, S>, FIteratorImpl, FSentinelImpl>;
using FSentinel = TConditional<CSameAs<W, S>, FIteratorImpl, FSentinelImpl>;
FORCEINLINE constexpr TIotaView() requires (CDefaultConstructible<W>) = default;
@ -122,13 +122,13 @@ public:
FORCEINLINE constexpr explicit TIotaView(TIdentity<W> InValue, TIdentity<S> InLast) : First(InValue), Last(InLast) { }
FORCEINLINE constexpr explicit TIotaView(Iterator InFirst, Sentinel InLast) : First(InFirst.Value), Last(InLast.Value) { }
FORCEINLINE constexpr explicit TIotaView(FIterator InFirst, FSentinel InLast) : First(InFirst.Value), Last(InLast.Value) { }
FORCEINLINE constexpr explicit TIotaView(Iterator InFirst, FUnreachableSentinel) requires (CSameAs<S, FUnreachableSentinel>) : First(InFirst.Value) { }
FORCEINLINE constexpr explicit TIotaView(FIterator InFirst, FUnreachableSentinel) requires (CSameAs<S, FUnreachableSentinel>) : First(InFirst.Value) { }
NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(First); }
NODISCARD FORCEINLINE constexpr FIterator Begin() const { return FIterator(First); }
NODISCARD FORCEINLINE constexpr Sentinel End() const { return Sentinel(Last); }
NODISCARD FORCEINLINE constexpr FSentinel End() const { return FSentinel(Last); }
NODISCARD FORCEINLINE constexpr size_t Num() const requires ((CIntegral<W> && CIntegral<S>) || CSizedSentinelFor<S, W>) { return Last - First; }
@ -143,13 +143,13 @@ private:
{
public:
using ElementType = TRemoveCV<W>;
using FElementType = TRemoveCV<W>;
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<W>) = default;
NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CEqualityComparable<W>) { return LHS.Value == RHS.Value; }
NODISCARD FORCEINLINE constexpr Reference operator*() const { return Value; }
NODISCARD FORCEINLINE constexpr FReference operator*() const { return Value; }
NODISCARD FORCEINLINE constexpr const W* operator->() const { return AddressOf(Value); }
FORCEINLINE constexpr FIteratorImpl& operator++() { ++Value; return *this; }
@ -207,13 +207,13 @@ private:
public:
using ElementType = W;
using FElementType = W;
using Reference = const W&;
using FReference = const W&;
using Iterator = FIteratorImpl;
using FIterator = FIteratorImpl;
using Sentinel = TConditional<bIsUnreachable, FUnreachableSentinel, Iterator>;
using FSentinel = TConditional<bIsUnreachable, FUnreachableSentinel, FIterator>;
FORCEINLINE constexpr TRepeatView() requires (CDefaultConstructible<W>) = default;
@ -228,16 +228,16 @@ public:
template <typename... Ts> requires (CConstructibleFrom<W, Ts...>)
FORCEINLINE constexpr explicit TRepeatView(FInPlace, Ts&&... Args, size_t InCount) : Value(Forward<Ts>(Args)...), Count(InCount) { }
NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(Value, 0); }
NODISCARD FORCEINLINE constexpr FIterator Begin() const { return FIterator(Value, 0); }
NODISCARD FORCEINLINE constexpr Sentinel End() const
NODISCARD FORCEINLINE constexpr FSentinel End() const
{
if constexpr (bIsUnreachable)
{
return UnreachableSentinel;
}
else return Sentinel(Value, Count);
else return FSentinel(Value, Count);
}
NODISCARD FORCEINLINE constexpr size_t Num() const requires (!bIsUnreachable) { return Count; }
@ -254,7 +254,7 @@ private:
{
public:
using ElementType = W;
using FElementType = W;
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<W>) = default;
@ -262,10 +262,10 @@ private:
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const FIteratorImpl& LHS, const FIteratorImpl& RHS) { return LHS.Current <=> RHS.Current; }
NODISCARD FORCEINLINE constexpr Reference operator*() const { return *Ptr; }
NODISCARD FORCEINLINE constexpr FReference operator*() const { return *Ptr; }
NODISCARD FORCEINLINE constexpr const W* operator->() const { return Ptr; }
NODISCARD FORCEINLINE constexpr Reference operator[](ptrdiff) const { return *Ptr; }
NODISCARD FORCEINLINE constexpr FReference operator[](ptrdiff) const { return *Ptr; }
FORCEINLINE constexpr FIteratorImpl& operator++() { ++Current; return *this; }
FORCEINLINE constexpr FIteratorImpl& operator--() { --Current; return *this; }

View File

@ -2,6 +2,7 @@
#include "CoreTypes.h"
#include "Range/View.h"
#include "Range/Pipe.h"
#include "Range/Utility.h"
#include "Range/AllView.h"
#include "Memory/Address.h"
@ -30,20 +31,20 @@ private:
public:
using ElementType = TRangeElement<V>;
using Reference = TRangeReference<V>;
using FElementType = TRangeElement<V>;
using FReference = TRangeReference<V>;
using Iterator = FIteratorImpl;
using FIterator = FIteratorImpl;
using Sentinel = TConditional<CCommonRange<V>, FIteratorImpl, FSentinelImpl>;
using FSentinel = TConditional<CCommonRange<V>, FIteratorImpl, FSentinelImpl>;
FORCEINLINE constexpr TFilterView() requires (CDefaultConstructible<V> && CDefaultConstructible<Pred>) = default;
FORCEINLINE constexpr explicit TFilterView(V InBase, Pred InPredicate) : Base(MoveTemp(InBase)), Predicate(MoveTemp(InPredicate)) { }
NODISCARD FORCEINLINE constexpr Iterator Begin()
NODISCARD FORCEINLINE constexpr FIterator Begin()
{
Iterator Iter(*this, Range::Begin(Base));
FIterator Iter(*this, Range::Begin(Base));
do
{
@ -60,7 +61,7 @@ public:
return Iter;
}
NODISCARD FORCEINLINE constexpr Sentinel End() { return Sentinel(*this, Range::End(Base)); }
NODISCARD FORCEINLINE constexpr FSentinel End() { return FSentinel(*this, Range::End(Base)); }
NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible<V>) { return Base; }
NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); }
@ -78,7 +79,7 @@ private:
public:
using ElementType = TIteratorElementType<TRangeIterator<V>>;
using FElementType = TIteratorElementType<TRangeIterator<V>>;
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<V>>) { } // Use '{ }' instead of '= default;' to avoid MSVC bug.
@ -174,10 +175,10 @@ NODISCARD FORCEINLINE constexpr auto Filter(R&& Base, Pred&& Predicate)
template <typename Pred>
NODISCARD FORCEINLINE constexpr auto Filter(Pred&& Predicate)
{
return [&Predicate]<CViewableRange R> requires (requires { TFilterView(DeclVal<R&&>(), DeclVal<Pred&&>()); }) (R&& Base)
return TAdaptorClosure([&Predicate]<CViewableRange R> requires (requires { Range::Filter(DeclVal<R&&>(), DeclVal<Pred&&>()); }) (R&& Base)
{
return TFilterView(Forward<R>(Base), Forward<Pred>(Predicate));
};
return Range::Filter(Forward<R>(Base), Forward<Pred>(Predicate));
});
}
NAMESPACE_END(Range)

View File

@ -0,0 +1,119 @@
#pragma once
#include "CoreTypes.h"
#include "Range/Utility.h"
#include "Templates/Invoke.h"
#include "Templates/Utility.h"
#include "TypeTraits/TypeTraits.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_BEGIN(Range)
/**
* An interface class template for defining a range adaptor closure.
* When the derived class has a unary operator() with range as a reference and is not itself a range,
* the derived class is the range adaptor closure type and its objects can participate in pipe operations.
* Specify, the unary operator() with any reference qualifier or cv-qualifier must be defined and has same effect.
* Not directly instantiable.
*/
template <CObject D> requires (CSameAs<D, TRemoveCV<D>>)
class IAdaptorClosure { };
/** An adaptor closure helper that wraps a callable object. */
template <CMoveConstructible F>
class TAdaptorClosure : public IAdaptorClosure<TAdaptorClosure<F>>
{
public:
FORCEINLINE constexpr explicit TAdaptorClosure(F InClosure) : Closure(MoveTemp(InClosure)) { }
template <typename R> requires (CInvocable<F&, R>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) &
{
return Invoke(Closure, Forward<R>(Range));
}
template <typename R> requires (CInvocable<const F&, R>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&
{
return Invoke(Closure, Forward<R>(Range));
}
template <typename R> requires (CInvocable<F&&, R>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) &&
{
return Invoke(MoveTemp(Closure), Forward<R>(Range));
}
template <typename R> requires (CInvocable<const F&&, R>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&&
{
return Invoke(MoveTemp(Closure), Forward<R>(Range));
}
private:
NO_UNIQUE_ADDRESS F Closure;
};
/** A pipe closure that wraps two adaptor closures. */
template <CMoveConstructible T, CMoveConstructible U> requires (CDerivedFrom<T, IAdaptorClosure<T>> && CDerivedFrom<U, IAdaptorClosure<U>>)
class TPipeClosure final : public IAdaptorClosure<TPipeClosure<T, U>>
{
public:
FORCEINLINE constexpr explicit TPipeClosure(T InLHS, U InRHS) : LHS(MoveTemp(InLHS)), RHS(MoveTemp(InRHS)) { }
template <typename R> requires (CInvocable<T&, R> && CInvocable<U&, TInvokeResult<T&, R>>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) &
{
return Forward<R>(Range) | LHS | RHS;
}
template <typename R> requires (CInvocable<const T&, R> && CInvocable<const U&, TInvokeResult<const T&, R>>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&
{
return Forward<R>(Range) | LHS | RHS;
}
template <typename R> requires (CInvocable<T&&, R> && CInvocable<U&&, TInvokeResult<T&&, R>>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) &&
{
return Forward<R>(Range) | MoveTemp(LHS) | MoveTemp(RHS);
}
template <typename R> requires (CInvocable<const T&&, R> && CInvocable<const U&&, TInvokeResult<const T&&, R>>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&&
{
return Forward<R>(Range) | MoveTemp(LHS) | MoveTemp(RHS);
}
private:
NO_UNIQUE_ADDRESS T LHS;
NO_UNIQUE_ADDRESS U RHS;
};
/** Apply the range adaptor closure to the range. */
template <CRange R, CInvocable<R> T> requires (CDerivedFrom<TRemoveCVRef<T>, IAdaptorClosure<TRemoveCVRef<T>>>)
NODISCARD FORCEINLINE constexpr auto operator|(R&& Range, T&& Closure)
{
return Invoke(Forward<T>(Closure), Forward<R>(Range));
}
/** Create a pipe closure that wraps two adaptor closures. */
template <CMoveConstructible T, CMoveConstructible U> requires (CDerivedFrom<T, IAdaptorClosure<T>> && CDerivedFrom<U, IAdaptorClosure<U>>)
NODISCARD FORCEINLINE constexpr auto operator|(T LHS, U RHS)
{
return TPipeClosure(MoveTemp(LHS), MoveTemp(RHS));
}
NAMESPACE_END(Range)
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -4,6 +4,7 @@
#include "Range/Utility.h"
#include "Range/View.h"
#include "Range/Factory.h"
#include "Range/Pipe.h"
#include "Range/AllView.h"
#include "Range/FilterView.h"
#include "Range/TransformView.h"

View File

@ -2,6 +2,7 @@
#include "CoreTypes.h"
#include "Range/View.h"
#include "Range/Pipe.h"
#include "Range/Utility.h"
#include "Range/AllView.h"
#include "Templates/Invoke.h"
@ -88,7 +89,7 @@ private:
public:
using ElementType = TRemoveCVRef<TInvokeResult<FFunc&, TRangeReference<FBase>>>;
using FElementType = TRemoveCVRef<TInvokeResult<FFunc&, TRangeReference<FBase>>>;
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<FBase>>) = default;
@ -221,10 +222,10 @@ NODISCARD FORCEINLINE constexpr auto Transform(R&& Base, F&& Func)
template <typename F>
NODISCARD FORCEINLINE constexpr auto Transform(F&& Func)
{
return [&Func]<CViewableRange R> requires (requires { TTransformView(DeclVal<R&&>(), DeclVal<F&&>()); }) (R&& Base)
return TAdaptorClosure([&Func]<CViewableRange R> requires (requires { Range::Transform(DeclVal<R&&>(), DeclVal<F&&>()); }) (R&& Base)
{
return TTransformView(Forward<R>(Base), Forward<F>(Func));
};
return Range::Transform(Forward<R>(Base), Forward<F>(Func));
});
}
NAMESPACE_END(Range)

View File

@ -11,7 +11,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_BEGIN(Range)
/** A helper class template for defining a view interface. Not directly instantiable. */
/** An interface class template for defining a view. Not directly instantiable. */
template <CClass T> requires (CSameAs<T, TRemoveCV<T>>)
class IBasicViewInterface
{
@ -100,7 +100,7 @@ class TRangeView : public IBasicViewInterface<TRangeView<I, S>>
{
public:
using ElementType = TIteratorElementType<I>;
using FElementType = TIteratorElementType<I>;
FORCEINLINE constexpr TRangeView() requires (CDefaultConstructible<I>) = default;

View File

@ -68,31 +68,31 @@ static_assert(CUnsigned<unicodechar>, "TChar assumes unicodechar is an unsigned
template <CCharType T>
struct TChar
{
using CharType = T;
using FCharType = T;
/** The maximum number of code units required to represent a single character. if unknown, guess 1. */
static constexpr size_t MaxCodeUnitLength =
CSameAs<CharType, char> ? MB_LEN_MAX :
CSameAs<CharType, wchar> ?
CSameAs<FCharType, char> ? MB_LEN_MAX :
CSameAs<FCharType, wchar> ?
PLATFORM_WINDOWS ? 2 :
PLATFORM_LINUX ? 1 : 1 :
CSameAs<CharType, u8char> ? 4 :
CSameAs<CharType, u16char> ? 2 :
CSameAs<CharType, u32char> ? 1 : 1;
CSameAs<FCharType, u8char> ? 4 :
CSameAs<FCharType, u16char> ? 2 :
CSameAs<FCharType, u32char> ? 1 : 1;
/** Whether the character type is fixed-length. */
static constexpr bool bIsFixedLength = MaxCodeUnitLength == 1;
NODISCARD FORCEINLINE static constexpr bool IsValid(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsValid(FCharType InChar)
{
if constexpr (CSameAs<CharType, u8char>)
if constexpr (CSameAs<FCharType, u8char>)
{
if ((InChar & 0b10000000) == 0b00000000) return true;
return false;
}
else if constexpr (CSameAs<CharType, u16char> || CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u16char> || CSameAs<FCharType, u32char>)
{
if (InChar >= 0xD800 && InChar <= 0xDBFF) return false;
if (InChar >= 0xDC00 && InChar <= 0xDFFF) return false;
@ -101,30 +101,30 @@ struct TChar
}
// Windows uses UTF-16 encoding for wchar.
else if constexpr (PLATFORM_WINDOWS && (CSameAs<CharType, wchar>))
else if constexpr (PLATFORM_WINDOWS && (CSameAs<FCharType, wchar>))
{
return TChar::IsValid(static_cast<u16char>(InChar));
}
// Linux uses UTF-32 encoding for wchar.
else if constexpr (PLATFORM_LINUX && (CSameAs<CharType, wchar>))
else if constexpr (PLATFORM_LINUX && (CSameAs<FCharType, wchar>))
{
return TChar::IsValid(static_cast<u32char>(InChar));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr bool IsNonch(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsNonch(FCharType InChar)
{
if constexpr (CSameAs<CharType, u8char>)
if constexpr (CSameAs<FCharType, u8char>)
{
return false;
}
else if constexpr (CSameAs<CharType, u16char>)
else if constexpr (CSameAs<FCharType, u16char>)
{
if (InChar >= U16TEXT('\uFDD0') && InChar <= U16TEXT('\uFDEF')) return true;
@ -134,7 +134,7 @@ struct TChar
return false;
}
else if constexpr (CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u32char>)
{
if (InChar >= U32TEXT('\uFDD0') && InChar <= U32TEXT('\uFDEF')) return true;
@ -144,25 +144,25 @@ struct TChar
}
// Windows uses UTF-16 encoding for wchar.
else if constexpr (PLATFORM_WINDOWS && (CSameAs<CharType, wchar>))
else if constexpr (PLATFORM_WINDOWS && (CSameAs<FCharType, wchar>))
{
return TChar::IsNonch(static_cast<u16char>(InChar));
}
// Linux uses UTF-32 encoding for wchar.
else if constexpr (PLATFORM_LINUX && (CSameAs<CharType, wchar>))
else if constexpr (PLATFORM_LINUX && (CSameAs<FCharType, wchar>))
{
return TChar::IsNonch(static_cast<u32char>(InChar));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr bool IsASCII(CharType InChar = LITERAL(CharType, '\0'))
NODISCARD FORCEINLINE static constexpr bool IsASCII(FCharType InChar = LITERAL(FCharType, '\0'))
{
if constexpr (CSameAs<CharType, char>)
if constexpr (CSameAs<FCharType, char>)
{
constexpr bool ASCIICompatible = []() -> bool
{
@ -188,7 +188,7 @@ struct TChar
return ASCIICompatible && 0x00 <= InChar && InChar <= 0x7F;
}
else if constexpr (CSameAs<CharType, wchar>)
else if constexpr (CSameAs<FCharType, wchar>)
{
constexpr bool ASCIICompatible = []() -> bool
{
@ -214,19 +214,19 @@ struct TChar
return ASCIICompatible && 0x00 <= InChar && InChar <= 0x7F;
}
else if constexpr (CSameAs<CharType, u8char> || CSameAs<CharType, u16char> || CSameAs<CharType, u32char> || CSameAs<CharType, unicodechar>)
else if constexpr (CSameAs<FCharType, u8char> || CSameAs<FCharType, u16char> || CSameAs<FCharType, u32char> || CSameAs<FCharType, unicodechar>)
{
return InChar <= 0x7F;
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr bool IsAlnum(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsAlnum(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isalnum(InChar, Loc);
@ -237,15 +237,15 @@ struct TChar
}
}
NODISCARD FORCEINLINE static constexpr bool IsAlpha(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsAlpha(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isalpha(InChar, Loc);
}
else if constexpr (CSameAs<CharType, u8char>)
else if constexpr (CSameAs<FCharType, u8char>)
{
/*
* BASIC LATIN
@ -258,29 +258,29 @@ struct TChar
return false;
}
else if constexpr (CSameAs<CharType, u16char> || CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u16char> || CSameAs<FCharType, u32char>)
{
checkf(InChar <= LITERAL(CharType, '\u007F'), TEXT("TChar::IsAlpha() only supports basic latin block."));
checkf(InChar <= LITERAL(FCharType, '\u007F'), TEXT("TChar::IsAlpha() only supports basic latin block."));
if (InChar > LITERAL(CharType, '\u007F')) return false;
if (InChar > LITERAL(FCharType, '\u007F')) return false;
return TChar<u8char>::IsAlpha(static_cast<u8char>(InChar));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr bool IsLower(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsLower(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::islower(InChar, Loc);
}
else if constexpr (CSameAs<CharType, u8char>)
else if constexpr (CSameAs<FCharType, u8char>)
{
/*
* BASIC LATIN
@ -291,7 +291,7 @@ struct TChar
return false;
}
else if constexpr (CSameAs<CharType, u16char>)
else if constexpr (CSameAs<FCharType, u16char>)
{
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsLower() only supports basic latin block."));
@ -300,7 +300,7 @@ struct TChar
return TChar<u8char>::IsLower(static_cast<u8char>(InChar));
}
else if constexpr (CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u32char>)
{
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsLower() only supports basic latin block."));
@ -309,20 +309,20 @@ struct TChar
return TChar<u8char>::IsLower(static_cast<u8char>(InChar));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr bool IsUpper(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsUpper(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isupper(InChar, Loc);
}
else if constexpr (CSameAs<CharType, u8char>)
else if constexpr (CSameAs<FCharType, u8char>)
{
/*
* BASIC LATIN
@ -333,7 +333,7 @@ struct TChar
return false;
}
else if constexpr (CSameAs<CharType, u16char>)
else if constexpr (CSameAs<FCharType, u16char>)
{
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsUpper() only supports basic latin block."));
@ -342,7 +342,7 @@ struct TChar
return TChar<u8char>::IsUpper(static_cast<u8char>(InChar));
}
else if constexpr (CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u32char>)
{
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsUpper() only supports basic latin block."));
@ -351,20 +351,20 @@ struct TChar
return TChar<u8char>::IsUpper(static_cast<u8char>(InChar));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr bool IsDigit(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsDigit(FCharType InChar)
{
static_assert(TChar::IsASCII());
/* <U0030>..<U0039>; */
return InChar >= LITERAL(CharType, '0') && InChar <= LITERAL(CharType, '9');
return InChar >= LITERAL(FCharType, '0') && InChar <= LITERAL(FCharType, '9');
}
NODISCARD FORCEINLINE static constexpr bool IsDigit(CharType InChar, unsigned Base)
NODISCARD FORCEINLINE static constexpr bool IsDigit(FCharType InChar, unsigned Base)
{
checkf(Base >= 2 && Base <= 36, TEXT("Base must be in the range [2, 36]."));
@ -373,32 +373,32 @@ struct TChar
bool bResult = false;
/* <U0030>..<U0039>; */
bResult |= InChar >= LITERAL(CharType, '0') && InChar < LITERAL(CharType, '0') + static_cast<signed>(Base);
bResult |= InChar >= LITERAL(FCharType, '0') && InChar < LITERAL(FCharType, '0') + static_cast<signed>(Base);
/* <U0041>..<U0046>; */
bResult |= InChar >= LITERAL(CharType, 'a') && InChar < LITERAL(CharType, 'a') + static_cast<signed>(Base) - 10;
bResult |= InChar >= LITERAL(FCharType, 'a') && InChar < LITERAL(FCharType, 'a') + static_cast<signed>(Base) - 10;
/* <U0061>..<U0066>; */
bResult |= InChar >= LITERAL(CharType, 'A') && InChar < LITERAL(CharType, 'A') + static_cast<signed>(Base) - 10;
bResult |= InChar >= LITERAL(FCharType, 'A') && InChar < LITERAL(FCharType, 'A') + static_cast<signed>(Base) - 10;
return bResult;
}
NODISCARD FORCEINLINE static constexpr bool IsCntrl(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsCntrl(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::iscntrl(InChar, Loc);
}
else if constexpr (CSameAs<CharType, u8char>)
else if constexpr (CSameAs<FCharType, u8char>)
{
/* <U0000>..<U001F>;<U007F>; */
return (InChar >= U8TEXT('\u0000') && InChar <= U8TEXT('\u001F')) || InChar == U8TEXT('\u007F');
}
else if constexpr (CSameAs<CharType, u16char>)
else if constexpr (CSameAs<FCharType, u16char>)
{
/* <U0000>..<U001F>;<U007F>..<U009F>;<U2028>;<U2029>; */
return
@ -407,7 +407,7 @@ struct TChar
(InChar == U16TEXT('\u2028') || InChar == U16TEXT('\u2029'));
}
else if constexpr (CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u32char>)
{
/* <U0000>..<U001F>;<U007F>..<U009F>;<U2028>;<U2029>; */
return
@ -416,20 +416,20 @@ struct TChar
(InChar == U32TEXT('\u2028') || InChar == U32TEXT('\u2029'));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr bool IsGraph(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsGraph(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isgraph(InChar, Loc);
}
else if constexpr (CSameAs<CharType, u8char>)
else if constexpr (CSameAs<FCharType, u8char>)
{
/*
* BASIC LATIN
@ -440,7 +440,7 @@ struct TChar
return false;
}
else if constexpr (CSameAs<CharType, u16char>)
else if constexpr (CSameAs<FCharType, u16char>)
{
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsGraph() only supports basic latin block."));
@ -449,7 +449,7 @@ struct TChar
return TChar<u8char>::IsGraph(static_cast<u8char>(InChar));
}
else if constexpr (CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u32char>)
{
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsGraph() only supports basic latin block."));
@ -458,20 +458,20 @@ struct TChar
return TChar<u8char>::IsGraph(static_cast<u8char>(InChar));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr bool IsSpace(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsSpace(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isspace(InChar, Loc);
}
else if constexpr (CSameAs<CharType, u8char>)
else if constexpr (CSameAs<FCharType, u8char>)
{
/*
* ISO/IEC 6429
@ -488,7 +488,7 @@ struct TChar
return false;
}
else if constexpr (CSameAs<CharType, u16char>)
else if constexpr (CSameAs<FCharType, u16char>)
{
/*
* ISO/IEC 6429
@ -533,7 +533,7 @@ struct TChar
return false;
}
else if constexpr (CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u32char>)
{
/*
* ISO/IEC 6429
@ -578,26 +578,26 @@ struct TChar
return false;
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr bool IsBlank(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsBlank(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isblank(InChar, Loc);
}
else if constexpr (CSameAs<CharType, u8char>)
else if constexpr (CSameAs<FCharType, u8char>)
{
/* <U0009>;<U0020>; */
return InChar == U8TEXT('\u0009') || InChar == U8TEXT('\u0020');
}
else if constexpr (CSameAs<CharType, u16char>)
else if constexpr (CSameAs<FCharType, u16char>)
{
/* <U0009>;<U0020>;<U1680>;<U180E>;<U2000>..<U2006>;<U2008>..<U200A>;<U205F>;<U3000>; */
return
@ -608,7 +608,7 @@ struct TChar
(InChar == U16TEXT('\u205F') || InChar == U16TEXT('\u3000'));
}
else if constexpr (CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u32char>)
{
/* <U0009>;<U0020>;<U1680>;<U180E>;<U2000>..<U2006>;<U2008>..<U200A>;<U205F>;<U3000>; */
return
@ -619,20 +619,20 @@ struct TChar
(InChar == U32TEXT('\u205F') || InChar == U32TEXT('\u3000'));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr bool IsPrint(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsPrint(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isprint(InChar, Loc);
}
else if constexpr (CSameAs<CharType, u8char>)
else if constexpr (CSameAs<FCharType, u8char>)
{
/*
* BASIC LATIN
@ -643,7 +643,7 @@ struct TChar
return false;
}
else if constexpr (CSameAs<CharType, u16char>)
else if constexpr (CSameAs<FCharType, u16char>)
{
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsPrint() only supports basic latin block."));
@ -652,7 +652,7 @@ struct TChar
return TChar<u8char>::IsPrint(static_cast<u8char>(InChar));
}
else if constexpr (CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u32char>)
{
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsPrint() only supports basic latin block."));
@ -661,20 +661,20 @@ struct TChar
return TChar<u8char>::IsPrint(static_cast<u8char>(InChar));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr bool IsPunct(CharType InChar)
NODISCARD FORCEINLINE static constexpr bool IsPunct(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::ispunct(InChar, Loc);
}
else if constexpr (CSameAs<CharType, u8char>)
else if constexpr (CSameAs<FCharType, u8char>)
{
/*
* BASIC LATIN
@ -689,7 +689,7 @@ struct TChar
return false;
}
else if constexpr (CSameAs<CharType, u16char>)
else if constexpr (CSameAs<FCharType, u16char>)
{
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsPunct() only supports basic latin block."));
@ -698,7 +698,7 @@ struct TChar
return TChar<u8char>::IsPunct(static_cast<u8char>(InChar));
}
else if constexpr (CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u32char>)
{
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsPunct() only supports basic latin block."));
@ -707,20 +707,20 @@ struct TChar
return TChar<u8char>::IsPunct(static_cast<u8char>(InChar));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false;
}
NODISCARD FORCEINLINE static constexpr CharType ToLower(CharType InChar)
NODISCARD FORCEINLINE static constexpr FCharType ToLower(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return static_cast<CharType>(NAMESPACE_STD::tolower(InChar, Loc));
return static_cast<FCharType>(NAMESPACE_STD::tolower(InChar, Loc));
}
else if constexpr (CSameAs<CharType, u8char>)
else if constexpr (CSameAs<FCharType, u8char>)
{
/*
* BASIC LATIN
@ -737,7 +737,7 @@ struct TChar
return InChar;
}
else if constexpr (CSameAs<CharType, u16char>)
else if constexpr (CSameAs<FCharType, u16char>)
{
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::ToLower() only supports basic latin block."));
@ -746,7 +746,7 @@ struct TChar
return static_cast<u16char>(TChar<u8char>::ToLower(static_cast<u8char>(InChar)));
}
else if constexpr (CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u32char>)
{
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::ToLower() only supports basic latin block."));
@ -755,20 +755,20 @@ struct TChar
return static_cast<u16char>(TChar<u8char>::ToLower(static_cast<u8char>(InChar)));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return InChar;
}
NODISCARD FORCEINLINE static constexpr CharType ToUpper(CharType InChar)
NODISCARD FORCEINLINE static constexpr FCharType ToUpper(FCharType InChar)
{
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
{
NAMESPACE_STD::locale Loc("");
return static_cast<CharType>(NAMESPACE_STD::toupper(InChar, Loc));
return static_cast<FCharType>(NAMESPACE_STD::toupper(InChar, Loc));
}
else if constexpr (CSameAs<CharType, u8char>)
else if constexpr (CSameAs<FCharType, u8char>)
{
/*
* BASIC LATIN
@ -785,7 +785,7 @@ struct TChar
return InChar;
}
else if constexpr (CSameAs<CharType, u16char>)
else if constexpr (CSameAs<FCharType, u16char>)
{
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::ToUpper() only supports basic latin block."));
@ -794,7 +794,7 @@ struct TChar
return static_cast<u16char>(TChar<u8char>::ToUpper(static_cast<u8char>(InChar)));
}
else if constexpr (CSameAs<CharType, u32char>)
else if constexpr (CSameAs<FCharType, u32char>)
{
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::ToUpper() only supports basic latin block."));
@ -803,12 +803,12 @@ struct TChar
return static_cast<u16char>(TChar<u8char>::ToUpper(static_cast<u8char>(InChar)));
}
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return InChar;
}
NODISCARD FORCEINLINE static constexpr unsigned ToDigit(CharType InChar)
NODISCARD FORCEINLINE static constexpr unsigned ToDigit(FCharType InChar)
{
static_assert(TChar::IsASCII());
@ -834,12 +834,12 @@ struct TChar
static_assert(sizeof(DigitFromChar) == 256);
if constexpr (sizeof(CharType) > 1) if (InChar >> 8) return DigitFromChar[0];
if constexpr (sizeof(FCharType) > 1) if (InChar >> 8) return DigitFromChar[0];
return DigitFromChar[InChar];
}
NODISCARD FORCEINLINE static constexpr unsigned ToDigit(CharType InChar, bool bLowercase)
NODISCARD FORCEINLINE static constexpr unsigned ToDigit(FCharType InChar, bool bLowercase)
{
static_assert(TChar::IsASCII());
@ -867,7 +867,7 @@ struct TChar
static_assert(sizeof(DigitFromChar) == 256);
if constexpr (sizeof(CharType) > 1) if (InChar >> 8) return DigitFromChar[0];
if constexpr (sizeof(FCharType) > 1) if (InChar >> 8) return DigitFromChar[0];
return DigitFromChar[InChar];
}
@ -894,25 +894,25 @@ struct TChar
static_assert(sizeof(DigitFromChar) == 256);
if constexpr (sizeof(CharType) > 1) if (InChar >> 8) return DigitFromChar[0];
if constexpr (sizeof(FCharType) > 1) if (InChar >> 8) return DigitFromChar[0];
return DigitFromChar[InChar];
}
NODISCARD FORCEINLINE static constexpr CharType FromDigit(unsigned InDigit)
NODISCARD FORCEINLINE static constexpr FCharType FromDigit(unsigned InDigit)
{
checkf(InDigit < 36, TEXT("Digit must be in the range [0, 35]."));
return LITERAL(CharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit];
return LITERAL(FCharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit];
}
NODISCARD FORCEINLINE static constexpr CharType FromDigit(unsigned InDigit, bool bLowercase)
NODISCARD FORCEINLINE static constexpr FCharType FromDigit(unsigned InDigit, bool bLowercase)
{
checkf(InDigit < 36, TEXT("Digit must be in the range [0, 35]."));
if (bLowercase) return LITERAL(CharType, "0123456789abcdefghijklmnopqrstuvwxyz")[InDigit];
if (bLowercase) return LITERAL(FCharType, "0123456789abcdefghijklmnopqrstuvwxyz")[InDigit];
return LITERAL(CharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit];
return LITERAL(FCharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit];
}
};

View File

@ -264,6 +264,7 @@ struct TStringObjectFormatter
{
static bool Do(auto& Result, auto& Object, auto Param)
{
// ReSharper disable once CppInconsistentNaming
using U = TRemoveCVRef<decltype(Object)>;
if constexpr (!CConst<TRemoveReference<decltype(Object)>>)
@ -1065,9 +1066,9 @@ struct TStringObjectFormatter
}
}
using UnsignedU = TMakeUnsigned<U>;
using FUnsignedU = TMakeUnsigned<U>;
UnsignedU Unsigned = static_cast<UnsignedU>(Object);
FUnsignedU Unsigned = static_cast<FUnsignedU>(Object);
bool bNegative = false;
@ -1077,11 +1078,11 @@ struct TStringObjectFormatter
{
bNegative = true;
Unsigned = static_cast<UnsignedU>(-Unsigned);
Unsigned = static_cast<FUnsignedU>(-Unsigned);
}
}
constexpr size_t BufferSize = sizeof(UnsignedU) * 8 + 4;
constexpr size_t BufferSize = sizeof(FUnsignedU) * 8 + 4;
T Buffer[BufferSize];
@ -1111,8 +1112,8 @@ struct TStringObjectFormatter
case 6:
case 7:
case 9:
case 10: do { *--Iter = static_cast<T>('0' + Unsigned % Param.Base); Unsigned = static_cast<UnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
default: do { *--Iter = TChar<T>::FromDigit(Unsigned % Param.Base, bLowercase); Unsigned = static_cast<UnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
case 10: do { *--Iter = static_cast<T>('0' + Unsigned % Param.Base); Unsigned = static_cast<FUnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
default: do { *--Iter = TChar<T>::FromDigit(Unsigned % Param.Base, bLowercase); Unsigned = static_cast<FUnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
}
}
else
@ -1130,12 +1131,12 @@ struct TStringObjectFormatter
case 6:
case 7:
case 9:
case 10: do { *--Iter = static_cast<T>('0' + Unsigned % Param.Base); Unsigned = static_cast<UnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
default: do { *--Iter = TChar<T>::FromDigit(Unsigned % Param.Base); Unsigned = static_cast<UnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
case 10: do { *--Iter = static_cast<T>('0' + Unsigned % Param.Base); Unsigned = static_cast<FUnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
default: do { *--Iter = TChar<T>::FromDigit(Unsigned % Param.Base); Unsigned = static_cast<FUnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
}
}
}
else do { *--Iter = static_cast<T>('0' + Unsigned % 10); Unsigned = static_cast<UnsignedU>(Unsigned / 10); } while (Unsigned != 0);
else do { *--Iter = static_cast<T>('0' + Unsigned % 10); Unsigned = static_cast<FUnsignedU>(Unsigned / 10); } while (Unsigned != 0);
T* DigitBegin = Iter;
@ -1144,7 +1145,7 @@ struct TStringObjectFormatter
{
const size_t Padding = Param.Padding - (DigitEnd - DigitBegin);
if (Param.Padding < sizeof(UnsignedU) * 8) for (size_t Index = 0; Index != Padding; ++Index) *--Iter = LITERAL(T, '0');
if (Param.Padding < sizeof(FUnsignedU) * 8) for (size_t Index = 0; Index != Padding; ++Index) *--Iter = LITERAL(T, '0');
}
// Append the prefix to the buffer.
@ -1171,7 +1172,7 @@ struct TStringObjectFormatter
{
const size_t Padding = Param.Padding - (DigitEnd - DigitBegin);
if (Param.Padding > sizeof(UnsignedU) * 8)
if (Param.Padding > sizeof(FUnsignedU) * 8)
{
Result.Reserve(Result.Num() + (DigitBegin - Iter) + Param.Padding);
@ -1349,6 +1350,7 @@ struct TStringObjectParser
{
static bool Do(auto& View, auto& Object, auto Param)
{
// ReSharper disable once CppInconsistentNaming
using U = TRemoveCVRef<decltype(Object)>;
if constexpr (CConst<TRemoveReference<decltype(Object)>>)
@ -2200,17 +2202,17 @@ struct TStringObjectParser
return TChar<T>::ToDigit(Char);
};
using UnsignedU = TMakeUnsigned<U>;
using FUnsignedU = TMakeUnsigned<U>;
// The limit value that can be stored in an unsigned integer.
constexpr UnsignedU UnsignedMaximum = static_cast<UnsignedU>(-1);
constexpr FUnsignedU UnsignedMaximum = static_cast<FUnsignedU>(-1);
// The limit value that can be stored in a signed integer.
constexpr U SignedMaximum = static_cast<U>(UnsignedMaximum >> 1);
constexpr U SignedMinimum = -static_cast<U>(SignedMaximum) - 1;
UnsignedU LastValue = 0;
UnsignedU Unsigned = 0;
FUnsignedU LastValue = 0;
FUnsignedU Unsigned = 0;
if (TrimmedView.IsEmpty()) return false;
@ -2223,7 +2225,7 @@ struct TStringObjectParser
TrimmedView.RemovePrefix(1);
Unsigned = static_cast<UnsignedU>(Digit);
Unsigned = static_cast<FUnsignedU>(Digit);
while (!TrimmedView.IsEmpty())
{
@ -2235,7 +2237,7 @@ struct TStringObjectParser
LastValue = Unsigned;
Unsigned = static_cast<UnsignedU>(LastValue * Base + Digit);
Unsigned = static_cast<FUnsignedU>(LastValue * Base + Digit);
if (Unsigned < LastValue) return false;
}
@ -2245,11 +2247,11 @@ struct TStringObjectParser
if constexpr (CSigned<U>)
{
// Handle overflow.
if (!bNegative && Unsigned >= static_cast<UnsignedU>(SignedMaximum)) return false;
if ( bNegative && Unsigned >= static_cast<UnsignedU>(SignedMinimum)) return false;
if (!bNegative && Unsigned >= static_cast<FUnsignedU>(SignedMaximum)) return false;
if ( bNegative && Unsigned >= static_cast<FUnsignedU>(SignedMinimum)) return false;
// Handle negative sign.
if (bNegative) Unsigned = static_cast<UnsignedU>(-Unsigned);
if (bNegative) Unsigned = static_cast<FUnsignedU>(-Unsigned);
}
Object = static_cast<U>(Unsigned);
@ -2705,14 +2707,14 @@ NAMESPACE_PRIVATE_END
template <CCharType T, CAllocator<T> Allocator>
template <typename ... Ts>
void TString<T, Allocator>::AppendFormat(TStringView<ElementType> Fmt, const Ts&... Args)
void TString<T, Allocator>::AppendFormat(TStringView<FElementType> Fmt, const Ts&... Args)
{
// The Unreal Engine says that the starting buffer size catches 99.97% of printf calls.
constexpr size_t ReserveBufferSize = 512;
TString<T, TInlineAllocator<ReserveBufferSize>> Result;
NAMESPACE_PRIVATE::TStringFormatOrParseHelper<ElementType, true>::Do(Result, Fmt, ForwardAsTuple(Args...));
NAMESPACE_PRIVATE::TStringFormatOrParseHelper<FElementType, true>::Do(Result, Fmt, ForwardAsTuple(Args...));
Append(Result.Begin(), Result.End());
}
@ -2721,13 +2723,13 @@ template <CCharType T>
template <typename ... Ts>
size_t TStringView<T>::ParseAndTrim(TStringView Fmt, Ts&... Args)
{
return NAMESPACE_PRIVATE::TStringFormatOrParseHelper<ElementType, false>::Do(*this, Fmt, ForwardAsTuple(Args...));
return NAMESPACE_PRIVATE::TStringFormatOrParseHelper<FElementType, false>::Do(*this, Fmt, ForwardAsTuple(Args...));
}
template <CCharType T, CAllocator<T> Allocator>
void TString<T, Allocator>::AppendBool(bool Value)
{
NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Invalid);
NAMESPACE_PRIVATE::TStringObjectFormatter<FElementType>::Do(*this, AsConst(Value), Invalid);
}
template <CCharType T, CAllocator<T> Allocator>
@ -2738,13 +2740,13 @@ void TString<T, Allocator>::AppendInt(U Value, unsigned Base)
struct { unsigned Base; } Param = { Base };
NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Param);
NAMESPACE_PRIVATE::TStringObjectFormatter<FElementType>::Do(*this, AsConst(Value), Param);
}
template <CCharType T, CAllocator<T> Allocator> template <CFloatingPoint U> requires (!CConst<U> && !CVolatile<U>)
void TString<T, Allocator>::AppendFloat(U Value)
{
NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Invalid);
NAMESPACE_PRIVATE::TStringObjectFormatter<FElementType>::Do(*this, AsConst(Value), Invalid);
}
template <CCharType T, CAllocator<T> Allocator> template <CFloatingPoint U> requires (!CConst<U> && !CVolatile<U>)
@ -2752,7 +2754,7 @@ void TString<T, Allocator>::AppendFloat(U Value, bool bFixed, bool bScientific)
{
struct { bool bFixed; bool bScientific; } Param = { bFixed, bScientific };
NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Param);
NAMESPACE_PRIVATE::TStringObjectFormatter<FElementType>::Do(*this, AsConst(Value), Param);
}
template <CCharType T, CAllocator<T> Allocator> template <CFloatingPoint U> requires (!CConst<U> && !CVolatile<U>)
@ -2760,7 +2762,7 @@ void TString<T, Allocator>::AppendFloat(U Value, bool bFixed, bool bScientific,
{
struct { bool bFixed; bool bScientific; unsigned Precision; } Param = { bFixed, bScientific, Precision };
NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Param);
NAMESPACE_PRIVATE::TStringObjectFormatter<FElementType>::Do(*this, AsConst(Value), Param);
}
template <CCharType T>
@ -2768,9 +2770,9 @@ constexpr bool TStringView<T>::ToBoolAndTrim()
{
bool Value = false;
if (!NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, Value, Invalid))
if (!NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, Value, Invalid))
{
if (int IntValue; NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, IntValue, Invalid))
if (int IntValue; NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, IntValue, Invalid))
{
Value = IntValue != 0;
}
@ -2789,7 +2791,7 @@ constexpr U TStringView<T>::ToIntAndTrim(unsigned Base)
struct { unsigned Base; } Param = { Base };
NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, Value, Param);
NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, Value, Param);
return Value;
}
@ -2802,7 +2804,7 @@ constexpr U TStringView<T>::ToFloatAndTrim(bool bFixed, bool bScientific)
struct { bool bFixed; bool bScientific; } Param = { bFixed, bScientific };
NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, Value, Param);
NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, Value, Param);
return Value;
}

View File

@ -35,33 +35,33 @@ class TString : public TArray<T, Allocator>
{
private:
using Super = TArray<T, Allocator>;
using FSuper = TArray<T, Allocator>;
public:
using ElementType = typename Super::ElementType;
using AllocatorType = typename Super::AllocatorType;
using FElementType = typename FSuper::FElementType;
using FAllocatorType = typename FSuper::FAllocatorType;
using Reference = typename Super:: Reference;
using ConstReference = typename Super::ConstReference;
using FReference = typename FSuper:: FReference;
using FConstReference = typename FSuper::FConstReference;
using Iterator = typename Super:: Iterator;
using ConstIterator = typename Super::ConstIterator;
using FIterator = typename FSuper:: FIterator;
using FConstIterator = typename FSuper::FConstIterator;
using ReverseIterator = typename Super:: ReverseIterator;
using ConstReverseIterator = typename Super::ConstReverseIterator;
using FReverseIterator = typename FSuper:: FReverseIterator;
using FConstReverseIterator = typename FSuper::FConstReverseIterator;
static_assert(CContiguousIterator< Iterator>);
static_assert(CContiguousIterator<ConstIterator>);
static_assert(CContiguousIterator< FIterator>);
static_assert(CContiguousIterator<FConstIterator>);
/** Default constructor. Constructs an empty string. */
FORCEINLINE TString() = default;
/** Constructs the string with 'Count' copies of characters with 'InValue'. */
FORCEINLINE TString(size_t Count, ElementType InChar) : Super(Count, InChar) { }
FORCEINLINE TString(size_t Count, FElementType InChar) : FSuper(Count, InChar) { }
/** Constructs a string with the contents of the range ['InPtr', 'InPtr' + 'Count'). */
FORCEINLINE TString(const ElementType* InPtr, size_t Count) : TString(TStringView<ElementType>(InPtr, Count))
FORCEINLINE TString(const FElementType* InPtr, size_t Count) : TString(TStringView<FElementType>(InPtr, Count))
{
checkf(InPtr != nullptr, TEXT("TString cannot be initialized by nullptr. Please check the pointer."));
}
@ -69,7 +69,7 @@ public:
FORCEINLINE TString(nullptr_t, size_t) = delete;
/** Constructs a string with the contents of the range ['InPtr', '\0'). */
FORCEINLINE TString(const ElementType* InPtr) : TString(TStringView<ElementType>(InPtr))
FORCEINLINE TString(const FElementType* InPtr) : TString(TStringView<FElementType>(InPtr))
{
checkf(InPtr != nullptr, TEXT("TString cannot be initialized by nullptr. Please check the pointer."));
}
@ -77,11 +77,11 @@ public:
FORCEINLINE TString(nullptr_t) = delete;
/** Constructs the string with the contents of the 'View'. */
FORCEINLINE TString(TStringView<ElementType> View) : TString(View.Begin(), View.End()) { }
FORCEINLINE TString(TStringView<FElementType> View) : TString(View.Begin(), View.End()) { }
/** Constructs the string with the contents of the range ['First', 'Last'). */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
FORCEINLINE TString(I First, S Last) : Super(MoveTemp(First), MoveTemp(Last)) { }
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
FORCEINLINE TString(I First, S Last) : FSuper(MoveTemp(First), MoveTemp(Last)) { }
/** Copy constructor. Constructs the string with the copy of the contents of 'InValue'. */
FORCEINLINE TString(const TString&) = default;
@ -90,7 +90,7 @@ public:
FORCEINLINE TString(TString&&) = default;
/** Constructs the string with the contents of the initializer list. */
FORCEINLINE TString(initializer_list<ElementType> IL) : TString(Iteration::Begin(IL), Iteration::End(IL)) { }
FORCEINLINE TString(initializer_list<FElementType> IL) : TString(Iteration::Begin(IL), Iteration::End(IL)) { }
/** Copy assignment operator. Replaces the contents with a copy of the contents of 'InValue'. */
FORCEINLINE TString& operator=(const TString&) = default;
@ -99,27 +99,27 @@ public:
FORCEINLINE TString& operator=(TString&&) = default;
/** Compares the contents of two strings. */
NODISCARD friend FORCEINLINE 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<FElementType>(LHS) == TStringView<FElementType>(RHS); }
/** Compares the contents of a string and a character. */
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); }
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, FElementType RHS) { return TStringView<FElementType>(LHS) == RHS; }
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, const FElementType* RHS) { return TStringView<FElementType>(LHS) == RHS; }
NODISCARD friend FORCEINLINE bool operator==( FElementType LHS, const TString& RHS) { return LHS == TStringView<FElementType>(RHS); }
NODISCARD friend FORCEINLINE bool operator==(const FElementType* LHS, const TString& RHS) { return LHS == TStringView<FElementType>(RHS); }
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
NODISCARD friend FORCEINLINE 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<FElementType>(LHS) <=> TStringView<FElementType>(RHS); }
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
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); }
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, FElementType RHS) { return TStringView<FElementType>(LHS) <=> RHS; }
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, const FElementType* RHS) { return TStringView<FElementType>(LHS) <=> RHS; }
NODISCARD friend FORCEINLINE auto operator<=>( FElementType LHS, const TString& RHS) { return LHS <=> TStringView<FElementType>(RHS); }
NODISCARD friend FORCEINLINE auto operator<=>(const FElementType* LHS, const TString& RHS) { return LHS <=> TStringView<FElementType>(RHS); }
public:
/** Inserts 'InValue' before 'Index' in the string. */
FORCEINLINE Iterator Insert(size_t Index, ElementType InValue)
FORCEINLINE FIterator Insert(size_t Index, FElementType InValue)
{
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
@ -127,15 +127,15 @@ public:
}
/** Inserts 'InValue' before 'Iter' in the string. */
FORCEINLINE Iterator Insert(ConstIterator Iter, ElementType InValue)
FORCEINLINE FIterator Insert(FConstIterator Iter, FElementType InValue)
{
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
return Super::Insert(Iter, InValue);
return FSuper::Insert(Iter, InValue);
}
/** Inserts 'Count' copies of the 'InValue' before 'Index' in the string. */
FORCEINLINE Iterator Insert(size_t Index, size_t Count, ElementType InValue)
FORCEINLINE FIterator Insert(size_t Index, size_t Count, FElementType InValue)
{
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
@ -143,15 +143,15 @@ public:
}
/** Inserts 'Count' copies of the 'InValue' before 'Iter' in the string. */
FORCEINLINE Iterator Insert(ConstIterator Iter, size_t Count, ElementType InValue)
FORCEINLINE FIterator Insert(FConstIterator Iter, size_t Count, FElementType InValue)
{
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
return Super::Insert(Iter, Count, InValue);
return FSuper::Insert(Iter, Count, InValue);
}
/** Inserts characters from the 'View' before 'Index' in the string. */
FORCEINLINE Iterator Insert(size_t Index, TStringView<ElementType> View)
FORCEINLINE FIterator Insert(size_t Index, TStringView<FElementType> View)
{
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
@ -159,7 +159,7 @@ public:
}
/** Inserts characters from the 'View' before 'Iter' in the string. */
FORCEINLINE Iterator Insert(ConstIterator Iter, TStringView<ElementType> View)
FORCEINLINE FIterator Insert(FConstIterator Iter, TStringView<FElementType> View)
{
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
@ -167,8 +167,8 @@ public:
}
/** Inserts characters from the range ['First', 'Last') before 'Index' in the string. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
FORCEINLINE Iterator Insert(size_t Index, I First, S Last)
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
FORCEINLINE FIterator Insert(size_t Index, I First, S Last)
{
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
@ -176,16 +176,16 @@ public:
}
/** Inserts characters from the range ['First', 'Last') before 'Iter'. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
FORCEINLINE Iterator Insert(ConstIterator Iter, I First, S Last)
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
FORCEINLINE FIterator Insert(FConstIterator Iter, I First, S Last)
{
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
return Super::Insert(Iter, MoveTemp(First), MoveTemp(Last));
return FSuper::Insert(Iter, MoveTemp(First), MoveTemp(Last));
}
/** Inserts characters from the initializer list before 'Index' in the string. */
FORCEINLINE Iterator Insert(size_t Index, initializer_list<ElementType> IL)
FORCEINLINE FIterator Insert(size_t Index, initializer_list<FElementType> IL)
{
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
@ -193,15 +193,15 @@ public:
}
/** Inserts characters from the initializer list before 'Iter' in the string. */
FORCEINLINE Iterator Insert(ConstIterator Iter, initializer_list<ElementType> IL)
FORCEINLINE FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL)
{
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
return Super::Insert(Iter, IL);
return FSuper::Insert(Iter, IL);
}
/** Erases the character at 'Index' in the string. But it may change the order of characters. */
FORCEINLINE Iterator Erase(size_t Index, bool bAllowShrinking = true)
FORCEINLINE FIterator Erase(size_t Index, bool bAllowShrinking = true)
{
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index < Num()."));
@ -209,15 +209,15 @@ public:
}
/** Erases the character at 'Iter' in the string. But it may change the order of characters. */
FORCEINLINE Iterator Erase(ConstIterator Iter, bool bAllowShrinking = true)
FORCEINLINE FIterator Erase(FConstIterator Iter, bool bAllowShrinking = true)
{
checkf(this->IsValidIterator(Iter) && Iter != this->End(), TEXT("Read access violation. Please check IsValidIterator()."));
return Super::StableErase(Iter, bAllowShrinking);
return FSuper::StableErase(Iter, bAllowShrinking);
}
/** Erases 'CountToErase' characters starting from 'Index' in the string. But it may change the order of characters. */
FORCEINLINE Iterator Erase(size_t Index, size_t CountToErase, bool bAllowShrinking = true)
FORCEINLINE FIterator Erase(size_t Index, size_t CountToErase, bool bAllowShrinking = true)
{
checkf(Index <= this->Num() && Index + CountToErase <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToErase."));
@ -226,24 +226,24 @@ public:
}
/** Erases the characters in the range ['First', 'Last') in the string. But it may change the order of characters. */
FORCEINLINE Iterator Erase(ConstIterator First, ConstIterator Last, bool bAllowShrinking = true)
FORCEINLINE FIterator Erase(FConstIterator First, FConstIterator Last, bool bAllowShrinking = true)
{
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
return Super::StableErase(First, Last, bAllowShrinking);
return FSuper::StableErase(First, Last, bAllowShrinking);
}
/** Here, the 'Erase' is already stable and there is no need to provide 'StableErase'. */
void StableErase(...) = delete;
/** Appends 'Count' copies of the 'InValue' to the end of the string. */
TString& Append(size_t Count, ElementType InChar) { return Append(MakeCountedConstantIterator(InChar, Count), DefaultSentinel); }
TString& Append(size_t Count, FElementType InChar) { return Append(MakeCountedConstantIterator(InChar, Count), DefaultSentinel); }
/** Appends the contents of the 'View' to the end of the string. */
FORCEINLINE TString& Append(TStringView<ElementType> View) { return Append(View.Begin(), View.End()); }
FORCEINLINE TString& Append(TStringView<FElementType> View) { return Append(View.Begin(), View.End()); }
/** Appends the contents of the range ['First', 'Last') to the end of the string. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
TString& Append(I First, S Last)
{
if constexpr (CForwardIterator<I>)
@ -258,7 +258,7 @@ public:
for (size_t Index = CurrentNum; Index != CurrentNum + Count; ++Index)
{
(*this)[Index] = ElementType(*First++);
(*this)[Index] = FElementType(*First++);
}
}
else
@ -270,40 +270,40 @@ public:
}
/** Appends the contents of the initializer list to the end of the string. */
FORCEINLINE TString& Append(initializer_list<ElementType> IL) { return Append(Iteration::Begin(IL), Iteration::End(IL)); }
FORCEINLINE TString& Append(initializer_list<FElementType> IL) { return Append(Iteration::Begin(IL), Iteration::End(IL)); }
/** Appends the given character value to the end of the string. */
FORCEINLINE TString& operator+=(ElementType InChar) { return Append(1, InChar); }
FORCEINLINE TString& operator+=(FElementType InChar) { return Append(1, InChar); }
/** Appends the contents of the 'View' to the end of the string. */
FORCEINLINE TString& operator+=(TStringView<ElementType> View) { return Append(View); }
FORCEINLINE TString& operator+=(TStringView<FElementType> View) { return Append(View); }
/** Appends the contents of the range ['First', 'Last') to the end of the string. */
FORCEINLINE TString& operator+=(initializer_list<ElementType> IL) { return Append(IL); }
FORCEINLINE TString& operator+=(initializer_list<FElementType> IL) { return Append(IL); }
/** Concatenates two strings. */
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, const TString& RHS) { return TString(LHS).Append(RHS); }
/** Concatenates the string with the given character value. */
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, ElementType RHS) { return TString(LHS).Append(1, RHS); }
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, const ElementType* RHS) { return TString(LHS).Append( RHS); }
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, TStringView<ElementType> RHS) { return TString(LHS).Append( RHS); }
NODISCARD friend FORCEINLINE TString operator+( ElementType LHS, const TString& RHS) { return TString(1, LHS).Append(RHS); }
NODISCARD friend FORCEINLINE TString operator+( const ElementType* LHS, const TString& RHS) { return TString( LHS).Append(RHS); }
NODISCARD friend FORCEINLINE TString operator+(TStringView<ElementType> LHS, const TString& RHS) { return TString( LHS).Append(RHS); }
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, FElementType RHS) { return TString(LHS).Append(1, RHS); }
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, const FElementType* RHS) { return TString(LHS).Append( RHS); }
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, TStringView<FElementType> RHS) { return TString(LHS).Append( RHS); }
NODISCARD friend FORCEINLINE TString operator+( FElementType LHS, const TString& RHS) { return TString(1, LHS).Append(RHS); }
NODISCARD friend FORCEINLINE TString operator+( const FElementType* LHS, const TString& RHS) { return TString( LHS).Append(RHS); }
NODISCARD friend FORCEINLINE TString operator+(TStringView<FElementType> LHS, const TString& RHS) { return TString( LHS).Append(RHS); }
/** Concatenates two strings. The rvalue maybe modified. */
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, TString&& RHS) { LHS.Append(MoveTemp(RHS)); return LHS; }
/** Concatenates two strings. The rvalue maybe modified. */
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, ElementType RHS) { LHS.Append(1, RHS); return LHS; }
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, const ElementType* RHS) { LHS.Append( RHS); return LHS; }
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, TStringView<ElementType> RHS) { LHS.Append( RHS); return LHS; }
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, const TString<ElementType>& RHS) { LHS.Append( RHS); return LHS; }
NODISCARD friend FORCEINLINE TString operator+( ElementType LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
NODISCARD friend FORCEINLINE TString operator+( const ElementType* LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
NODISCARD friend FORCEINLINE TString operator+( TStringView<ElementType> LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
NODISCARD friend FORCEINLINE TString operator+(const TString<ElementType>& LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, FElementType RHS) { LHS.Append(1, RHS); return LHS; }
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, const FElementType* RHS) { LHS.Append( RHS); return LHS; }
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, TStringView<FElementType> RHS) { LHS.Append( RHS); return LHS; }
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, const TString<FElementType>& RHS) { LHS.Append( RHS); return LHS; }
NODISCARD friend FORCEINLINE TString operator+( FElementType LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
NODISCARD friend FORCEINLINE TString operator+( const FElementType* LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
NODISCARD friend FORCEINLINE TString operator+( TStringView<FElementType> LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
NODISCARD friend FORCEINLINE TString operator+(const TString<FElementType>& LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
public:
@ -330,7 +330,7 @@ public:
/** Removes whitespace characters from the start of this string. */
FORCEINLINE constexpr TString& TrimStart(bool bAllowShrinking = true)
{
auto Index = Find([](ElementType Char) { return !TChar<ElementType>::IsSpace(Char); });
auto Index = Find([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); });
if (Index != INDEX_NONE)
{
@ -344,7 +344,7 @@ public:
/** Removes whitespace characters from the end of this string. */
FORCEINLINE constexpr TString& TrimEnd(bool bAllowShrinking = true)
{
auto Index = RFind([](ElementType Char) { return !TChar<ElementType>::IsSpace(Char); });
auto Index = RFind([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); });
if (Index != INDEX_NONE)
{
@ -367,7 +367,7 @@ public:
/** Removes characters after the first null-terminator. */
FORCEINLINE constexpr TString& TrimToNullTerminator(bool bAllowShrinking = true)
{
auto Index = Find(LITERAL(ElementType, '\0'));
auto Index = Find(LITERAL(FElementType, '\0'));
if (Index != INDEX_NONE)
{
@ -380,50 +380,50 @@ public:
public:
/** @return true if the string view starts with the given prefix, false otherwise. */
NODISCARD FORCEINLINE bool StartsWith(TStringView<ElementType> Prefix) const
NODISCARD FORCEINLINE bool StartsWith(TStringView<FElementType> Prefix) const
{
return TStringView<ElementType>(*this).StartsWith(Prefix);
return TStringView<FElementType>(*this).StartsWith(Prefix);
}
/** @return true if the string view starts with the given prefix, false otherwise. */
NODISCARD FORCEINLINE bool StartsWith(ElementType Prefix) const
NODISCARD FORCEINLINE bool StartsWith(FElementType Prefix) const
{
return TStringView<ElementType>(*this).StartsWith(Prefix);
return TStringView<FElementType>(*this).StartsWith(Prefix);
}
/** @return true if the string view ends with the given suffix, false otherwise. */
NODISCARD FORCEINLINE bool EndsWith(TStringView<ElementType> Suffix) const
NODISCARD FORCEINLINE bool EndsWith(TStringView<FElementType> Suffix) const
{
return TStringView<ElementType>(*this).EndsWith(Suffix);
return TStringView<FElementType>(*this).EndsWith(Suffix);
}
/** @return true if the string view ends with the given suffix, false otherwise. */
NODISCARD FORCEINLINE bool EndsWith(ElementType Suffix) const
NODISCARD FORCEINLINE bool EndsWith(FElementType Suffix) const
{
return TStringView<ElementType>(*this).EndsWith(Suffix);
return TStringView<FElementType>(*this).EndsWith(Suffix);
}
/** @return true if the string view contains the given substring, false otherwise. */
NODISCARD FORCEINLINE bool Contains(TStringView<ElementType> View) const
NODISCARD FORCEINLINE bool Contains(TStringView<FElementType> View) const
{
return TStringView<ElementType>(*this).Contains(View);
return TStringView<FElementType>(*this).Contains(View);
}
/** @return true if the string view contains the given character, false otherwise. */
NODISCARD FORCEINLINE bool Contains(ElementType Char) const
NODISCARD FORCEINLINE bool Contains(FElementType Char) const
{
return TStringView<ElementType>(*this).Contains(Char);
return TStringView<FElementType>(*this).Contains(Char);
}
/** @return true if the string view contains character that satisfy the given predicate, false otherwise. */
template <CPredicate<ElementType> F>
template <CPredicate<FElementType> F>
NODISCARD FORCEINLINE bool Contains(F&& InPredicate) const
{
return TStringView<ElementType>(*this).Contains(Forward<F>(InPredicate));
return TStringView<FElementType>(*this).Contains(Forward<F>(InPredicate));
}
/** Replace the substring [Index, Index + CountToReplace) with 'Count' copies of the 'InChar'. */
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, size_t Count, ElementType InChar)
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, size_t Count, FElementType InChar)
{
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
@ -431,7 +431,7 @@ public:
}
/** Replace the substring ['First', 'Last') with 'Count' copies of the 'InChar'. */
FORCEINLINE TString& Replace(ConstIterator First, ConstIterator Last, size_t Count, ElementType InChar)
FORCEINLINE TString& Replace(FConstIterator First, FConstIterator Last, size_t Count, FElementType InChar)
{
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
@ -439,7 +439,7 @@ public:
}
/** Replace the substring [Index, Index + CountToReplace) with the contents of the 'View'. */
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, TStringView<ElementType> View)
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, TStringView<FElementType> View)
{
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
@ -447,7 +447,7 @@ public:
}
/** Replace the substring ['First', 'Last') with the contents of the 'View'. */
FORCEINLINE TString& Replace(ConstIterator First, ConstIterator Last, TStringView<ElementType> View)
FORCEINLINE TString& Replace(FConstIterator First, FConstIterator Last, TStringView<FElementType> View)
{
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
@ -455,7 +455,7 @@ public:
}
/** Replace the substring [Index, Index + CountToReplace) with the contents of the range ['First', 'Last'). */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, I InString, S Sentinel)
{
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
@ -464,8 +464,8 @@ public:
}
/** Replace the substring ['First', 'Last') with the contents of the range ['InString', 'Sentinel'). */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
TString& Replace(ConstIterator First, ConstIterator Last, I InString, S Sentinel)
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
TString& Replace(FConstIterator First, FConstIterator Last, I InString, S Sentinel)
{
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
@ -484,7 +484,7 @@ public:
{
for (size_t Index = InsertIndex; Index != InsertIndex + InsertCount; ++Index)
{
(*this)[Index] = ElementType(*InString++);
(*this)[Index] = FElementType(*InString++);
}
for (size_t Index = InsertIndex + InsertCount; Index != NumToReset; ++Index)
@ -505,7 +505,7 @@ public:
for (size_t Index = InsertIndex; Index != InsertIndex + InsertCount; ++Index)
{
(*this)[Index] = ElementType(*InString++);
(*this)[Index] = FElementType(*InString++);
}
}
}
@ -520,7 +520,7 @@ public:
}
/** Replace the substring [Index, Index + CountToReplace) with the contents of the initializer list. */
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, initializer_list<ElementType> IL)
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, initializer_list<FElementType> IL)
{
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
@ -528,7 +528,7 @@ public:
}
/** Replace the substring ['First', 'Last') with the contents of the initializer list. */
FORCEINLINE TString& Replace(ConstIterator First, ConstIterator Last, initializer_list<ElementType> IL)
FORCEINLINE TString& Replace(FConstIterator First, FConstIterator Last, initializer_list<FElementType> IL)
{
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
@ -540,133 +540,133 @@ public:
{
checkf(Offset <= this->Num() && Offset + Count <= this->Num(), TEXT("Illegal substring range. Please check Offset and Count."));
return TStringView<ElementType>(*this).Substr(Offset, Count);
return TStringView<FElementType>(*this).Substr(Offset, Count);
}
/** Copies the characters of this string to the destination buffer without null-termination. */
FORCEINLINE size_t Copy(ElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const
FORCEINLINE size_t Copy(FElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const
{
checkf(Dest != nullptr, TEXT("Illegal destination buffer. Please check the pointer."));
checkf(Offset <= this->Num() && (Count == DynamicExtent || Offset + Count <= this->Num()), TEXT("Illegal subview range. Please check Offset and Count."));
return TStringView<ElementType>(*this).Copy(Dest, Count, Offset);
return TStringView<FElementType>(*this).Copy(Dest, Count, Offset);
}
FORCEINLINE size_t Copy(nullptr_t, size_t = DynamicExtent, size_t = 0) const = delete;
/** @return The index of the first occurrence of the given substring, or INDEX_NONE if not found. */
NODISCARD size_t Find(TStringView<ElementType> View, size_t Index = 0) const
NODISCARD size_t Find(TStringView<FElementType> View, size_t Index = 0) const
{
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).Find(View, Index);
return TStringView<FElementType>(*this).Find(View, Index);
}
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
NODISCARD size_t Find(ElementType Char, size_t Index = 0) const
NODISCARD size_t Find(FElementType Char, size_t Index = 0) const
{
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).Find(Char, Index);
return TStringView<FElementType>(*this).Find(Char, Index);
}
/** @return The index of the first occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
template <CPredicate<ElementType> F>
template <CPredicate<FElementType> F>
NODISCARD size_t Find(F&& InPredicate, size_t Index = 0) const
{
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).Find(Forward<F>(InPredicate), Index);
return TStringView<FElementType>(*this).Find(Forward<F>(InPredicate), Index);
}
/** @return The index of the last occurrence of the given substring, or INDEX_NONE if not found. */
NODISCARD size_t RFind(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
NODISCARD size_t RFind(TStringView<FElementType> View, size_t Index = INDEX_NONE) const
{
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).RFind(View, Index);
return TStringView<FElementType>(*this).RFind(View, Index);
}
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
NODISCARD size_t RFind(ElementType Char, size_t Index = INDEX_NONE) const
NODISCARD size_t RFind(FElementType Char, size_t Index = INDEX_NONE) const
{
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).RFind(Char, Index);
return TStringView<FElementType>(*this).RFind(Char, Index);
}
/** @return The index of the last occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
template <CPredicate<ElementType> F>
template <CPredicate<FElementType> F>
NODISCARD size_t RFind(F&& InPredicate, size_t Index = INDEX_NONE) const
{
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).RFind(Forward<F>(InPredicate), Index);
return TStringView<FElementType>(*this).RFind(Forward<F>(InPredicate), Index);
}
/** @return The index of the first occurrence of the character contained in the given view, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE size_t FindFirstOf(TStringView<ElementType> View, size_t Index = 0) const
NODISCARD FORCEINLINE size_t FindFirstOf(TStringView<FElementType> View, size_t Index = 0) const
{
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).FindFirstOf(View, Index);
return TStringView<FElementType>(*this).FindFirstOf(View, Index);
}
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE size_t FindFirstOf(ElementType Char, size_t Index = 0) const
NODISCARD FORCEINLINE size_t FindFirstOf(FElementType Char, size_t Index = 0) const
{
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).FindFirstOf(Char, Index);
return TStringView<FElementType>(*this).FindFirstOf(Char, Index);
}
/** @return The index of the last occurrence of the character contained in the given view, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE size_t FindLastOf(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
NODISCARD FORCEINLINE size_t FindLastOf(TStringView<FElementType> View, size_t Index = INDEX_NONE) const
{
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).FindLastOf(View, Index);
return TStringView<FElementType>(*this).FindLastOf(View, Index);
}
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE size_t FindLastOf(ElementType Char, size_t Index = INDEX_NONE) const
NODISCARD FORCEINLINE size_t FindLastOf(FElementType Char, size_t Index = INDEX_NONE) const
{
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).FindLastOf(Char, Index);
return TStringView<FElementType>(*this).FindLastOf(Char, Index);
}
/** @return The index of the first absence of the character contained in the given view, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE size_t FindFirstNotOf(TStringView<ElementType> View, size_t Index = 0) const
NODISCARD FORCEINLINE size_t FindFirstNotOf(TStringView<FElementType> View, size_t Index = 0) const
{
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).FindFirstNotOf(View, Index);
return TStringView<FElementType>(*this).FindFirstNotOf(View, Index);
}
/** @return The index of the first absence of the given character, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE size_t FindFirstNotOf(ElementType Char, size_t Index = 0) const
NODISCARD FORCEINLINE size_t FindFirstNotOf(FElementType Char, size_t Index = 0) const
{
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).FindFirstNotOf(Char, Index);
return TStringView<FElementType>(*this).FindFirstNotOf(Char, Index);
}
/** @return The index of the last absence of the character contained in the given view, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE size_t FindLastNotOf(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
NODISCARD FORCEINLINE size_t FindLastNotOf(TStringView<FElementType> View, size_t Index = INDEX_NONE) const
{
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).FindLastNotOf(View, Index);
return TStringView<FElementType>(*this).FindLastNotOf(View, Index);
}
/** @return The index of the last absence of the given character, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE size_t FindLastNotOf(ElementType Char, size_t Index = INDEX_NONE) const
NODISCARD FORCEINLINE size_t FindLastNotOf(FElementType Char, size_t Index = INDEX_NONE) const
{
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
return TStringView<ElementType>(*this).FindLastNotOf(Char, Index);
return TStringView<FElementType>(*this).FindLastNotOf(Char, Index);
}
public:
@ -1028,7 +1028,7 @@ public:
{
if (this->Max() >= this->Num() + 1)
{
const_cast<ElementType*>(this->GetData())[this->Num()] = LITERAL(ElementType, '\0');
const_cast<FElementType*>(this->GetData())[this->Num()] = LITERAL(FElementType, '\0');
return *TStringView(this->GetData(), this->Num() + 1);
}
@ -1052,31 +1052,31 @@ public:
/** @return true if the string only contains valid characters, false otherwise. */
NODISCARD FORCEINLINE bool IsValid() const
{
return TStringView<ElementType>(*this).IsValid();
return TStringView<FElementType>(*this).IsValid();
}
/** @return true if the string only contains ASCII characters, false otherwise. */
NODISCARD FORCEINLINE bool IsASCII() const
{
return TStringView<ElementType>(*this).IsASCII();
return TStringView<FElementType>(*this).IsASCII();
}
/** @return true if the string can be fully represented as a boolean value, false otherwise. */
NODISCARD FORCEINLINE bool IsBoolean() const
{
return TStringView<ElementType>(*this).IsBoolean();
return TStringView<FElementType>(*this).IsBoolean();
}
/** @return true if the string can be fully represented as an integer value, false otherwise. */
NODISCARD FORCEINLINE bool IsInteger(unsigned Base = 10, bool bSigned = true) const
{
return TStringView<ElementType>(*this).IsInteger(Base, bSigned);
return TStringView<FElementType>(*this).IsInteger(Base, bSigned);
}
/** @return true if the string can be fully represented as a floating-point value, false otherwise. */
NODISCARD FORCEINLINE bool IsFloatingPoint(bool bFixed = true, bool bScientific = true, bool bSigned = true) const
{
return TStringView<ElementType>(*this).IsFloatingPoint(bFixed, bScientific, bSigned);
return TStringView<FElementType>(*this).IsFloatingPoint(bFixed, bScientific, bSigned);
}
public:
@ -1202,7 +1202,7 @@ public:
*/
NODISCARD FORCEINLINE bool ToBool() const
{
return TStringView<ElementType>(*this).ToBool();
return TStringView<FElementType>(*this).ToBool();
}
/**
@ -1223,7 +1223,7 @@ public:
{
checkf(Base >= 2 && Base <= 36, TEXT("Illegal base. Please check the base."));
return TStringView<ElementType>(*this).template ToInt<U>(Base);
return TStringView<FElementType>(*this).template ToInt<U>(Base);
}
/**
@ -1244,13 +1244,13 @@ public:
template <CFloatingPoint U = float> requires (!CConst<U> && !CVolatile<U>)
NODISCARD FORCEINLINE U ToFloat(bool bFixed = true, bool bScientific = false) const
{
return TStringView<ElementType>(*this).template ToFloat<U>(bFixed, bScientific);
return TStringView<FElementType>(*this).template ToFloat<U>(bFixed, bScientific);
}
/** Converts a string into a boolean value and remove the parsed substring. */
NODISCARD FORCEINLINE bool ToBoolAndTrim()
{
TStringView<ElementType> View = *this;
TStringView<FElementType> View = *this;
bool Result = View.ToBoolAndTrim();
@ -1265,7 +1265,7 @@ public:
template <CIntegral U = int> requires (!CSameAs<U, bool> && !CConst<U> && !CVolatile<U>)
NODISCARD FORCEINLINE U ToIntAndTrim(unsigned Base = 10)
{
TStringView<ElementType> View = *this;
TStringView<FElementType> View = *this;
U Result = View.template ToIntAndTrim<U>(Base);
@ -1280,7 +1280,7 @@ public:
template <CFloatingPoint U = float> requires (!CConst<U> && !CVolatile<U>)
NODISCARD FORCEINLINE U ToFloatAndTrim(bool bFixed = true, bool bScientific = true)
{
TStringView<ElementType> View = *this;
TStringView<FElementType> View = *this;
U Result = View.template ToFloatAndTrim<U>(bFixed, bScientific);
@ -1302,7 +1302,7 @@ public:
* @return The formatted string containing the objects.
*/
template <typename... Ts>
NODISCARD static FORCEINLINE TString Format(TStringView<ElementType> Fmt, const Ts&... Args)
NODISCARD static FORCEINLINE TString Format(TStringView<FElementType> Fmt, const Ts&... Args)
{
TString Result;
@ -1313,7 +1313,7 @@ public:
/** Format some objects using a format string and append to the string. */
template <typename... Ts>
void AppendFormat(TStringView<ElementType> Fmt, const Ts&... Args);
void AppendFormat(TStringView<FElementType> Fmt, const Ts&... Args);
/**
* Parse a string using a format string to objects.
@ -1324,16 +1324,16 @@ public:
* @return The number of objects successfully parsed.
*/
template <typename... Ts>
FORCEINLINE size_t Parse(TStringView<ElementType> Fmt, Ts&... Args) const
FORCEINLINE size_t Parse(TStringView<FElementType> Fmt, Ts&... Args) const
{
return TStringView(*this).Parse(Fmt, Args...);
}
/** Parse a string using a format string to objects and remove the parsed substring. */
template <typename... Ts>
FORCEINLINE size_t ParseAndTrim(TStringView<ElementType> Fmt, Ts&... Args)
FORCEINLINE size_t ParseAndTrim(TStringView<FElementType> Fmt, Ts&... Args)
{
TStringView<ElementType> View = *this;
TStringView<FElementType> View = *this;
size_t Result = View.ParseAndTrim(Fmt, Args...);
@ -1347,10 +1347,10 @@ public:
public:
/** Overloads the GetTypeHash algorithm for TString. */
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TString& A) { return GetTypeHash(TStringView<ElementType>(A)); }
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TString& A) { return GetTypeHash(TStringView<FElementType>(A)); }
/** Overloads the Swap algorithm for TString. */
friend FORCEINLINE void Swap(TString& A, TString& B) { Swap(static_cast<Super&>(A), static_cast<Super&>(B)); }
friend FORCEINLINE void Swap(TString& A, TString& B) { Swap(static_cast<FSuper&>(A), static_cast<FSuper&>(B)); }
};
@ -1373,7 +1373,7 @@ using FU16String = TString<u16char>;
using FU32String = TString<u32char>;
using FUnicodeString = TString<unicodechar>;
template <CCharType T> template <typename Allocator> constexpr TStringView<T>::TStringView(const TString<ElementType, Allocator>& InString)
template <CCharType T> template <typename Allocator> constexpr TStringView<T>::TStringView(const TString<FElementType, Allocator>& InString)
: TStringView(InString.GetData(), InString.Num()) { }
NAMESPACE_MODULE_END(Utility)

View File

@ -82,36 +82,36 @@ class TStringView : public TArrayView<const T>
{
private:
using Super = TArrayView<const T>;
using FSuper = TArrayView<const T>;
public:
using ElementType = T;
using FElementType = T;
using Reference = typename Super::Reference;
using FReference = typename FSuper::FReference;
using Iterator = typename Super::Iterator;
using ReverseIterator = typename Super::ReverseIterator;
using FIterator = typename FSuper:: FIterator;
using FReverseIterator = typename FSuper::FReverseIterator;
static_assert(CContiguousIterator<Iterator>);
static_assert(CContiguousIterator<FIterator>);
/** Constructs an empty string view. */
FORCEINLINE constexpr TStringView() = default;
/** Constructs a string view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */
template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const ElementType(*)[]>)
FORCEINLINE constexpr TStringView(I InFirst, size_t InCount) : Super(InFirst, InCount) { }
template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const FElementType(*)[]>)
FORCEINLINE constexpr TStringView(I InFirst, size_t InCount) : FSuper(InFirst, InCount) { }
/** Constructs a string view that is a view over the range ['InFirst', 'InLast'). */
template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const ElementType(*)[]>)
FORCEINLINE constexpr TStringView(I InFirst, S InLast) : Super(InFirst, InLast) { }
template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const FElementType(*)[]>)
FORCEINLINE constexpr TStringView(I InFirst, S InLast) : FSuper(InFirst, InLast) { }
/** Constructs a string view that is a view over the string 'InString'. */
template <typename Allocator>
FORCEINLINE constexpr TStringView(const TString<ElementType, Allocator>& InString);
FORCEINLINE constexpr TStringView(const TString<FElementType, Allocator>& InString);
/** Constructs a string view that is a view over the range ['InPtr', 'InPtr' + 'Count'). */
FORCEINLINE constexpr TStringView(const ElementType* InPtr, size_t Count) : Super(InPtr, Count)
FORCEINLINE constexpr TStringView(const FElementType* InPtr, size_t Count) : FSuper(InPtr, Count)
{
checkf(InPtr != nullptr, TEXT("TStringView cannot be initialized by nullptr. Please check the pointer."));
}
@ -119,23 +119,23 @@ public:
FORCEINLINE constexpr TStringView(nullptr_t, size_t) = delete;
/** Constructs a string view that is a view over the range ['InPtr', '\0'). */
FORCEINLINE constexpr TStringView(const ElementType* InPtr)
FORCEINLINE constexpr TStringView(const FElementType* InPtr)
{
checkf(InPtr != nullptr, TEXT("TStringView cannot be initialized by nullptr. Please check the pointer."));
size_t Length = 0;
if constexpr (CSameAs<ElementType, char>)
if constexpr (CSameAs<FElementType, char>)
{
Length = NAMESPACE_STD::strlen(InPtr);
}
else if constexpr (CSameAs<ElementType, wchar>)
else if constexpr (CSameAs<FElementType, wchar>)
{
Length = NAMESPACE_STD::wcslen(InPtr);
}
else
{
while (InPtr[Length] != LITERAL(ElementType, '\0')) ++Length;
while (InPtr[Length] != LITERAL(FElementType, '\0')) ++Length;
}
*this = TStringView(InPtr, Length);
@ -150,18 +150,18 @@ public:
FORCEINLINE constexpr TStringView& operator=(const TStringView&) noexcept = default;
/** Compares the contents of two string views. */
NODISCARD friend constexpr bool operator==(TStringView LHS, TStringView RHS) { return static_cast<Super>(LHS) == static_cast<Super>(RHS); }
NODISCARD friend constexpr bool operator==(TStringView LHS, TStringView RHS) { return static_cast<FSuper>(LHS) == static_cast<FSuper>(RHS); }
/** Compares the contents of a string view and a character. */
NODISCARD friend constexpr bool operator==(TStringView LHS, ElementType RHS) { return LHS == TStringView(&RHS, 1); }
NODISCARD friend constexpr bool operator==(ElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) == RHS; }
NODISCARD friend constexpr bool operator==(TStringView LHS, FElementType RHS) { return LHS == TStringView(&RHS, 1); }
NODISCARD friend constexpr bool operator==(FElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) == RHS; }
/** Compares the contents of two string views. */
NODISCARD friend constexpr auto operator<=>(TStringView LHS, TStringView RHS) { return static_cast<Super>(LHS) <=> static_cast<Super>(RHS); }
NODISCARD friend constexpr auto operator<=>(TStringView LHS, TStringView RHS) { return static_cast<FSuper>(LHS) <=> static_cast<FSuper>(RHS); }
/** Compares the contents of a string view and a character. */
NODISCARD friend constexpr auto operator<=>(TStringView LHS, ElementType RHS) { return LHS <=> TStringView(&RHS, 1); }
NODISCARD friend constexpr auto operator<=>(ElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) <=> RHS; }
NODISCARD friend constexpr auto operator<=>(TStringView LHS, FElementType RHS) { return LHS <=> TStringView(&RHS, 1); }
NODISCARD friend constexpr auto operator<=>(FElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) <=> RHS; }
public:
@ -188,7 +188,7 @@ public:
/** Removes whitespace characters from the start of this string. */
FORCEINLINE constexpr TStringView& TrimStart()
{
auto Index = Find([](ElementType Char) { return !TChar<ElementType>::IsSpace(Char); });
auto Index = Find([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); });
if (Index != INDEX_NONE)
{
@ -202,7 +202,7 @@ public:
/** Removes whitespace characters from the end of this string. */
FORCEINLINE constexpr TStringView& TrimEnd()
{
auto Index = RFind([](ElementType Char) { return !TChar<ElementType>::IsSpace(Char); });
auto Index = RFind([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); });
if (Index != INDEX_NONE)
{
@ -225,7 +225,7 @@ public:
/** Removes characters after the first null-terminator. */
FORCEINLINE constexpr TStringView& TrimToNullTerminator()
{
auto Index = Find(LITERAL(ElementType, '\0'));
auto Index = Find(LITERAL(FElementType, '\0'));
if (Index != INDEX_NONE)
{
@ -238,7 +238,7 @@ public:
public:
/** Copies the elements of this string view to the destination buffer without null-termination. */
FORCEINLINE constexpr size_t Copy(ElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const
FORCEINLINE constexpr size_t Copy(FElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const
{
checkf(Dest != nullptr, TEXT("Illegal destination buffer. Please check the pointer."));
@ -277,7 +277,7 @@ public:
{
checkf(Offset <= this->Num() && (Count == DynamicExtent || Offset + Count <= this->Num()), TEXT("Illegal subview range. Please check Offset and Count."));
Super Temp = this->Subview(Offset, Count);
FSuper Temp = this->Subview(Offset, Count);
return TStringView(Temp.GetData(), Temp.Num());
}
@ -289,7 +289,7 @@ public:
}
/** @return true if the string view starts with the given prefix, false otherwise. */
NODISCARD FORCEINLINE constexpr bool StartsWith(ElementType Prefix) const
NODISCARD FORCEINLINE constexpr bool StartsWith(FElementType Prefix) const
{
return this->Num() >= 1 && this->Front() == Prefix;
}
@ -301,7 +301,7 @@ public:
}
/** @return true if the string view ends with the given suffix, false otherwise. */
NODISCARD FORCEINLINE constexpr bool EndsWith(ElementType Suffix) const
NODISCARD FORCEINLINE constexpr bool EndsWith(FElementType Suffix) const
{
return this->Num() >= 1 && this->Back() == Suffix;
}
@ -313,13 +313,13 @@ public:
}
/** @return true if the string view contains the given character, false otherwise. */
NODISCARD FORCEINLINE constexpr bool Contains(ElementType Char) const
NODISCARD FORCEINLINE constexpr bool Contains(FElementType Char) const
{
return Find(Char) != INDEX_NONE;
}
/** @return true if the string view contains character that satisfy the given predicate, false otherwise. */
template <CPredicate<ElementType> F>
template <CPredicate<FElementType> F>
NODISCARD FORCEINLINE constexpr bool Contains(F&& InPredicate) const
{
return Find(Forward<F>(InPredicate)) != INDEX_NONE;
@ -346,7 +346,7 @@ public:
}
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
NODISCARD constexpr size_t Find(ElementType Char, size_t Index = 0) const
NODISCARD constexpr size_t Find(FElementType Char, size_t Index = 0) const
{
if (Index >= this->Num()) return INDEX_NONE;
@ -362,7 +362,7 @@ public:
}
/** @return The index of the first occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
template <CPredicate<ElementType> F>
template <CPredicate<FElementType> F>
NODISCARD constexpr size_t Find(F&& InPredicate, size_t Index = 0) const
{
if (Index >= this->Num()) return INDEX_NONE;
@ -401,7 +401,7 @@ public:
}
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
NODISCARD constexpr size_t RFind(ElementType Char, size_t Index = INDEX_NONE) const
NODISCARD constexpr size_t RFind(FElementType Char, size_t Index = INDEX_NONE) const
{
if (Index != INDEX_NONE && Index >= this->Num()) return INDEX_NONE;
@ -419,7 +419,7 @@ public:
}
/** @return The index of the last occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
template <CPredicate<ElementType> F>
template <CPredicate<FElementType> F>
NODISCARD constexpr size_t RFind(F&& InPredicate, size_t Index = INDEX_NONE) const
{
if (Index != INDEX_NONE && Index >= this->Num()) return INDEX_NONE;
@ -440,11 +440,11 @@ public:
/** @return The index of the first occurrence of the character contained in the given view, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE constexpr size_t FindFirstOf(TStringView View, size_t Index = 0) const
{
return Find([View](ElementType Char) { return View.Contains(Char); }, Index);
return Find([View](FElementType Char) { return View.Contains(Char); }, Index);
}
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE constexpr size_t FindFirstOf(ElementType Char, size_t Index = 0) const
NODISCARD FORCEINLINE constexpr size_t FindFirstOf(FElementType Char, size_t Index = 0) const
{
return Find(Char, Index);
}
@ -452,11 +452,11 @@ public:
/** @return The index of the last occurrence of the character contained in the given view, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE constexpr size_t FindLastOf(TStringView View, size_t Index = INDEX_NONE) const
{
return RFind([View](ElementType Char) { return View.Contains(Char); }, Index);
return RFind([View](FElementType Char) { return View.Contains(Char); }, Index);
}
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE constexpr size_t FindLastOf(ElementType Char, size_t Index = INDEX_NONE) const
NODISCARD FORCEINLINE constexpr size_t FindLastOf(FElementType Char, size_t Index = INDEX_NONE) const
{
return RFind(Char, Index);
}
@ -464,25 +464,25 @@ public:
/** @return The index of the first absence of the character contained in the given view, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE constexpr size_t FindFirstNotOf(TStringView View, size_t Index = 0) const
{
return Find([View](ElementType Char) { return !View.Contains(Char); }, Index);
return Find([View](FElementType Char) { return !View.Contains(Char); }, Index);
}
/** @return The index of the first absence of the given character, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE constexpr size_t FindFirstNotOf(ElementType Char, size_t Index = 0) const
NODISCARD FORCEINLINE constexpr size_t FindFirstNotOf(FElementType Char, size_t Index = 0) const
{
return Find([Char](ElementType C) { return C != Char; }, Index);
return Find([Char](FElementType C) { return C != Char; }, Index);
}
/** @return The index of the last absence of the character contained in the given view, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE constexpr size_t FindLastNotOf(TStringView View, size_t Index = INDEX_NONE) const
{
return RFind([View](ElementType Char) { return !View.Contains(Char); }, Index);
return RFind([View](FElementType Char) { return !View.Contains(Char); }, Index);
}
/** @return The index of the last absence of the given character, or INDEX_NONE if not found. */
NODISCARD FORCEINLINE constexpr size_t FindLastNotOf(ElementType Char, size_t Index = INDEX_NONE) const
NODISCARD FORCEINLINE constexpr size_t FindLastNotOf(FElementType Char, size_t Index = INDEX_NONE) const
{
return RFind([Char](ElementType C) { return C != Char; }, Index);
return RFind([Char](FElementType C) { return C != Char; }, Index);
}
public:
@ -490,18 +490,18 @@ public:
/** @return The non-modifiable standard C character string version of the string view. */
NODISCARD FORCEINLINE auto operator*() const
{
if (this->Back() == LITERAL(ElementType, '\0') || Contains(LITERAL(ElementType, '\0')))
if (this->Back() == LITERAL(FElementType, '\0') || Contains(LITERAL(FElementType, '\0')))
{
return NAMESPACE_PRIVATE::TCStringFromTStringView<ElementType>(this->GetData(), false);
return NAMESPACE_PRIVATE::TCStringFromTStringView<FElementType>(this->GetData(), false);
}
ElementType* Buffer = new ElementType[this->Num() + 1];
FElementType* Buffer = new FElementType[this->Num() + 1];
Copy(Buffer);
Buffer[this->Num()] = LITERAL(ElementType, '\0');
Buffer[this->Num()] = LITERAL(FElementType, '\0');
return NAMESPACE_PRIVATE::TCStringFromTStringView<ElementType>(Buffer, true);
return NAMESPACE_PRIVATE::TCStringFromTStringView<FElementType>(Buffer, true);
}
public:
@ -509,9 +509,9 @@ public:
/** @return true if the string only contains valid characters, false otherwise. */
NODISCARD constexpr bool IsValid() const
{
for (ElementType Char : *this)
for (FElementType Char : *this)
{
if (!TChar<ElementType>::IsValid(Char)) return false;
if (!TChar<FElementType>::IsValid(Char)) return false;
}
return true;
@ -520,9 +520,9 @@ public:
/** @return true if the string only contains ASCII characters, false otherwise. */
NODISCARD constexpr bool IsASCII() const
{
for (ElementType Char : *this)
for (FElementType Char : *this)
{
if (!TChar<ElementType>::IsASCII(Char)) return false;
if (!TChar<FElementType>::IsASCII(Char)) return false;
}
return true;
@ -543,7 +543,7 @@ public:
{
TStringView View = *this;
if (View.StartsWith(LITERAL(ElementType, '-')))
if (View.StartsWith(LITERAL(FElementType, '-')))
{
if (bSigned) View.RemovePrefix(1);
else return false;
@ -559,7 +559,7 @@ public:
{
TStringView View = *this;
if (View.StartsWith(LITERAL(ElementType, '-')))
if (View.StartsWith(LITERAL(FElementType, '-')))
{
if (bSigned) View.RemovePrefix(1);
else return false;
@ -659,7 +659,7 @@ public:
public:
/** Overloads the GetTypeHash algorithm for TStringView. */
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(TStringView A) { return GetTypeHash(static_cast<Super>(A)); }
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(TStringView A) { return GetTypeHash(static_cast<FSuper>(A)); }
};
@ -676,6 +676,8 @@ using FU16StringView = TStringView<u16char>;
using FU32StringView = TStringView<u32char>;
using FUnicodeStringView = TStringView<unicodechar>;
// ReSharper disable CppInconsistentNaming
#define TEXT_VIEW(X) TStringView(TEXT(X))
#define WTEXT_VIEW(X) TStringView(WTEXT(X))
#define U8TEXT_VIEW(X) TStringView(U8TEXT(X))
@ -685,6 +687,8 @@ using FUnicodeStringView = TStringView<unicodechar>;
#define LITERAL_VIEW(T, X) TStringView(LITERAL(T, X))
// ReSharper restore CppInconsistentNaming
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -15,9 +15,9 @@ NAMESPACE_MODULE_BEGIN(Utility)
// NOTE: In the STL, the assignment operation of the std::any type uses the copy-and-swap idiom
// instead of directly calling the assignment operation of the contained value.
// The purpose of this is as follows:
// 1) the copy assignment might not exist.
// 2) the typical case is that the objects are different.
// The purpose of this is as follows:
// 1) the copy assignment might not exist.
// 2) the typical case is that the objects are different.
// 3) it is less exception-safe
// But we don't follow the the copy-and-swap idiom, because we assume that no function throws an exception.
@ -107,7 +107,7 @@ public:
{
EmplaceImpl<T>(Forward<Ts>(Args)...);
}
/** Constructs an object with initial content an object of type TDecay<T>, direct-non-list-initialized from IL, Forward<Ts>(Args).... */
template <typename T, typename U, typename... Ts> requires (NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, initializer_list<U>, Ts&&...>)
FORCEINLINE explicit FAny(TInPlaceType<T>, initializer_list<U> IL, Ts&&... Args)
@ -244,23 +244,23 @@ public:
&& NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, T&&>)
FORCEINLINE FAny& operator=(T&& InValue)
{
using DecayedType = TDecay<T>;
using FDecayedType = TDecay<T>;
if constexpr (CAssignableFrom<DecayedType, T&&>)
if constexpr (CAssignableFrom<FDecayedType, T&&>)
{
if (HoldsAlternative<DecayedType>())
if (HoldsAlternative<FDecayedType>())
{
GetValue<DecayedType>() = Forward<T>(InValue);
GetValue<FDecayedType>() = Forward<T>(InValue);
return *this;
}
}
Destroy();
EmplaceImpl<DecayedType>(Forward<T>(InValue));
EmplaceImpl<FDecayedType>(Forward<T>(InValue));
return *this;
}
/** Check if the contained value is equivalent to 'InValue'. */
template <typename T> requires (!CSameAs<FAny, TRemoveCVRef<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CEqualityComparable<T>)
NODISCARD FORCEINLINE constexpr bool operator==(const T& InValue) const&
@ -352,12 +352,12 @@ public:
Destroy();
Invalidate();
}
/** Overloads the Swap algorithm for FAny. */
friend void Swap(FAny& A, FAny& B)
{
if (!A.IsValid() && !B.IsValid()) return;
if (A.IsValid() && !B.IsValid())
{
B = MoveTemp(A);
@ -524,7 +524,7 @@ private:
default: check_no_entry(); return nullptr;
}
}
FORCEINLINE const void* GetStorage() const
{
switch (GetRepresentation())
@ -536,36 +536,36 @@ private:
default: check_no_entry(); return nullptr;
}
}
template <typename T, typename... Ts>
void EmplaceImpl(Ts&&... Args)
{
using DecayedType = TDecay<T>;
using FDecayedType = TDecay<T>;
TypeInfo = reinterpret_cast<uintptr>(&typeid(DecayedType));
TypeInfo = reinterpret_cast<uintptr>(&typeid(FDecayedType));
if constexpr (CEmpty<DecayedType> && CTrivial<DecayedType>) return; // ERepresentation::Empty
if constexpr (CEmpty<FDecayedType> && CTrivial<FDecayedType>) return; // ERepresentation::Empty
constexpr bool bIsTriviallyStorable = sizeof(DecayedType) <= sizeof(TrivialStorage.Internal) && alignof(DecayedType) <= alignof(FAny) && CTriviallyCopyable<DecayedType>;
constexpr bool bIsSmallStorable = sizeof(DecayedType) <= sizeof( SmallStorage.Internal) && alignof(DecayedType) <= alignof(FAny);
constexpr bool bIsTriviallyStorable = sizeof(FDecayedType) <= sizeof(TrivialStorage.Internal) && alignof(FDecayedType) <= alignof(FAny) && CTriviallyCopyable<FDecayedType>;
constexpr bool bIsSmallStorable = sizeof(FDecayedType) <= sizeof( SmallStorage.Internal) && alignof(FDecayedType) <= alignof(FAny);
static constexpr const FRTTI SelectedRTTI(InPlaceType<DecayedType>);
static constexpr const FRTTI SelectedRTTI(InPlaceType<FDecayedType>);
if constexpr (bIsTriviallyStorable)
{
new (&TrivialStorage.Internal) DecayedType(Forward<Ts>(Args)...);
new (&TrivialStorage.Internal) FDecayedType(Forward<Ts>(Args)...);
TypeInfo |= static_cast<uintptr>(ERepresentation::Trivial);
}
else if constexpr (bIsSmallStorable)
{
new (&SmallStorage.Internal) DecayedType(Forward<Ts>(Args)...);
new (&SmallStorage.Internal) FDecayedType(Forward<Ts>(Args)...);
SmallStorage.RTTI = &SelectedRTTI;
TypeInfo |= static_cast<uintptr>(ERepresentation::Small);
}
else
{
BigStorage.External = Memory::Malloc(sizeof(DecayedType), alignof(DecayedType));
new (BigStorage.External) DecayedType(Forward<Ts>(Args)...);
BigStorage.External = Memory::Malloc(sizeof(FDecayedType), alignof(FDecayedType));
new (BigStorage.External) FDecayedType(Forward<Ts>(Args)...);
BigStorage.RTTI = &SelectedRTTI;
TypeInfo |= static_cast<uintptr>(ERepresentation::Big);
}

View File

@ -20,7 +20,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
* the values change in an order different from the order another thread wrote them. Indeed,
* the apparent order of changes can even differ among multiple reader threads. Some similar effects
* can occur even on uniprocessor systems due to compiler transformations allowed by the memory model.
*
*
* @see https://en.cppreference.com/w/cpp/atomic/memory_order
*/
enum class EMemoryOrder : uint8
@ -68,48 +68,48 @@ struct TAtomicImpl : FSingleton
{
protected:
using NativeAtomicType = TConditional<bIsRef, NAMESPACE_STD::atomic_ref<T>, NAMESPACE_STD::atomic<T>>;
using FNativeAtomic = TConditional<bIsRef, NAMESPACE_STD::atomic_ref<T>, NAMESPACE_STD::atomic<T>>;
public:
using ValueType = T;
using FValueType = T;
/** Indicates that the type is always lock-free */
static constexpr bool bIsAlwaysLockFree = NativeAtomicType::is_always_lock_free;
static constexpr bool bIsAlwaysLockFree = FNativeAtomic::is_always_lock_free;
/** Indicates the required alignment of an object to be referenced by TAtomicRef. */
static constexpr size_t RequiredAlignment = NAMESPACE_STD::atomic_ref<T>::required_alignment;
/** Constructs an atomic object. */
FORCEINLINE constexpr TAtomicImpl() requires (!bIsRef) : NativeAtomic() { };
FORCEINLINE constexpr TAtomicImpl(ValueType Desired) requires (!bIsRef) : NativeAtomic(Desired) { };
FORCEINLINE constexpr TAtomicImpl() requires (!bIsRef) : NativeAtomic() { }
FORCEINLINE constexpr TAtomicImpl(FValueType Desired) requires (!bIsRef) : NativeAtomic(Desired) { }
/** Constructs an atomic reference. */
FORCEINLINE explicit TAtomicImpl(ValueType& Desired) requires (bIsRef) : NativeAtomic(Desired) { check(Memory::IsAligned(&Desired, RequiredAlignment)); };
FORCEINLINE TAtomicImpl(TAtomicImpl& InValue) requires (bIsRef) : NativeAtomic(InValue) { };
FORCEINLINE explicit TAtomicImpl(FValueType& Desired) requires (bIsRef) : NativeAtomic(Desired) { check(Memory::IsAligned(&Desired, RequiredAlignment)); }
FORCEINLINE TAtomicImpl(TAtomicImpl& InValue) requires (bIsRef) : NativeAtomic(InValue) { }
/** Stores a value into an atomic object. */
FORCEINLINE ValueType operator=(ValueType Desired) { return NativeAtomic = Desired; }
FORCEINLINE ValueType operator=(ValueType Desired) volatile requires (bIsAlwaysLockFree) { return NativeAtomic = Desired; }
FORCEINLINE FValueType operator=(FValueType Desired) { return NativeAtomic = Desired; }
FORCEINLINE FValueType operator=(FValueType Desired) volatile requires (bIsAlwaysLockFree) { return NativeAtomic = Desired; }
/** Atomically replaces the value of the atomic object with a non-atomic argument. */
FORCEINLINE void Store(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.store(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE void Store(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.store(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE void Store(FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.store(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE void Store(FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.store(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Atomically obtains the value of the atomic object. */
NODISCARD FORCEINLINE ValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.load(static_cast<NAMESPACE_STD::memory_order>(Order)); }
NODISCARD FORCEINLINE ValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.load(static_cast<NAMESPACE_STD::memory_order>(Order)); }
NODISCARD FORCEINLINE FValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.load(static_cast<NAMESPACE_STD::memory_order>(Order)); }
NODISCARD FORCEINLINE FValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.load(static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Loads a value from an atomic object. */
NODISCARD FORCEINLINE operator ValueType() const { return static_cast<ValueType>(NativeAtomic); }
NODISCARD FORCEINLINE operator ValueType() const volatile requires (bIsAlwaysLockFree) { return static_cast<ValueType>(NativeAtomic); }
NODISCARD FORCEINLINE operator FValueType() const { return static_cast<FValueType>(NativeAtomic); }
NODISCARD FORCEINLINE operator FValueType() const volatile requires (bIsAlwaysLockFree) { return static_cast<FValueType>(NativeAtomic); }
/** Atomically replaces the value of the atomic object and obtains the value held previously. */
NODISCARD FORCEINLINE ValueType Exchange(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { return NativeAtomic.exchange(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
NODISCARD FORCEINLINE ValueType Exchange(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { return NativeAtomic.exchange(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
NODISCARD FORCEINLINE FValueType Exchange(FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { return NativeAtomic.exchange(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
NODISCARD FORCEINLINE FValueType Exchange(FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { return NativeAtomic.exchange(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false)
NODISCARD FORCEINLINE bool CompareExchange(FValueType& Expected, FValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false)
{
MEMORY_ORDER_CHECK(Failure, 0x01 | 0x02 | 0x04 | 0x20);
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Success), static_cast<NAMESPACE_STD::memory_order>(Failure));
@ -117,7 +117,7 @@ public:
}
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree)
NODISCARD FORCEINLINE bool CompareExchange(FValueType& Expected, FValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree)
{
MEMORY_ORDER_CHECK(Failure, 0x01 | 0x02 | 0x04 | 0x20);
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Success), static_cast<NAMESPACE_STD::memory_order>(Failure));
@ -125,162 +125,162 @@ public:
}
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false)
NODISCARD FORCEINLINE bool CompareExchange(FValueType& Expected, FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false)
{
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
else return NativeAtomic.compare_exchange_strong(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
}
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree)
NODISCARD FORCEINLINE bool CompareExchange(FValueType& Expected, FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree)
{
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
else return NativeAtomic.compare_exchange_strong(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
}
/** Blocks the thread until notified and the atomic value changes. */
FORCEINLINE void Wait(ValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); NativeAtomic.wait(Old, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE void Wait(ValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); NativeAtomic.wait(Old, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE void Wait(FValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); NativeAtomic.wait(Old, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE void Wait(FValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); NativeAtomic.wait(Old, static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Notifies at least one or all threads blocked waiting on the atomic object. */
FORCEINLINE void Notify(bool bIsAll = false) { if (bIsAll) NativeAtomic.notify_all(); else NativeAtomic.notify_one(); }
FORCEINLINE void Notify(bool bIsAll = false) volatile { if (bIsAll) NativeAtomic.notify_all(); else NativeAtomic.notify_one(); }
/** Atomically executes the 'Func' on the value stored in the atomic object and obtains the value held previously. */
template <typename F> requires (CInvocableResult<ValueType, F, ValueType>)
FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent)
template <typename F> requires (CInvocableResult<FValueType, F, FValueType>)
FORCEINLINE FValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent)
{
ValueType Temp(Load(EMemoryOrder::Relaxed));
FValueType Temp(Load(EMemoryOrder::Relaxed));
// We do a weak read here because we require a loop.
while (!CompareExchange(Temp, InvokeResult<ValueType>(Forward<F>(Func), Temp), Order, true));
while (!CompareExchange(Temp, InvokeResult<FValueType>(Forward<F>(Func), Temp), Order, true));
return Temp;
}
/** Atomically executes the 'Func' on the value stored in the atomic object and obtains the value held previously. */
template <typename F> requires (CInvocableResult<ValueType, F, ValueType> && bIsAlwaysLockFree)
FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile
template <typename F> requires (CInvocableResult<FValueType, F, FValueType> && bIsAlwaysLockFree)
FORCEINLINE FValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile
{
ValueType Temp(Load(EMemoryOrder::Relaxed));
FValueType Temp(Load(EMemoryOrder::Relaxed));
// We do a weak read here because we require a loop.
while (!CompareExchange(Temp, InvokeResult<ValueType>(Forward<F>(Func), Temp), Order, true));
while (!CompareExchange(Temp, InvokeResult<FValueType>(Forward<F>(Func), Temp), Order, true));
return Temp;
}
/** Atomically adds the argument to the value stored in the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchAdd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE ValueType FetchAdd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchAdd(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchAdd(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Atomically adds the argument to the value stored in the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer<T> ) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE ValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer<T> ) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Atomically subtracts the argument from the value stored in the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchSub(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE ValueType FetchSub(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchSub(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchSub(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Atomically subtracts the argument from the value stored in the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer<T> ) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE ValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer<T> ) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Atomically multiples the argument from the value stored in the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchMul(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old * InValue; }); }
FORCEINLINE ValueType FetchMul(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return FetchFn([InValue](ValueType Old) -> ValueType { return Old * InValue; }); }
FORCEINLINE FValueType FetchMul(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old * InValue; }); }
FORCEINLINE FValueType FetchMul(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return FetchFn([InValue](FValueType Old) -> FValueType { return Old * InValue; }); }
/** Atomically divides the argument from the value stored in the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchDiv(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old / InValue; }); }
FORCEINLINE ValueType FetchDiv(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return FetchFn([InValue](ValueType Old) -> ValueType { return Old / InValue; }); }
FORCEINLINE FValueType FetchDiv(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old / InValue; }); }
FORCEINLINE FValueType FetchDiv(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return FetchFn([InValue](FValueType Old) -> FValueType { return Old / InValue; }); }
/** Atomically models the argument from the value stored in the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchMod(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old % InValue; }); }
FORCEINLINE ValueType FetchMod(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old % InValue; }); }
FORCEINLINE FValueType FetchMod(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old % InValue; }); }
FORCEINLINE FValueType FetchMod(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old % InValue; }); }
/** Atomically performs bitwise AND between the argument and the value of the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchAnd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_and(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE ValueType FetchAnd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_and(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchAnd(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_and(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchAnd(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_and(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Atomically performs bitwise OR between the argument and the value of the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchOr(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_or(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE ValueType FetchOr(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_or(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchOr(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_or(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchOr(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_or(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Atomically performs bitwise XOR between the argument and the value of the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchXor(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_xor(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE ValueType FetchXor(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_xor(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchXor(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_xor(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchXor(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_xor(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Atomically performs bitwise LSH between the argument and the value of the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old << InValue; }); }
FORCEINLINE ValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old << InValue; }); }
FORCEINLINE FValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old << InValue; }); }
FORCEINLINE FValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old << InValue; }); }
/** Atomically performs bitwise RSH between the argument and the value of the atomic object and obtains the value held previously. */
FORCEINLINE ValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old >> InValue; }); }
FORCEINLINE ValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old >> InValue; }); }
/** Increments the atomic value by one. */
FORCEINLINE ValueType operator++() requires ((CIntegral<T> || CPointer<T>) ) { return ++NativeAtomic; }
FORCEINLINE ValueType operator++() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return ++NativeAtomic; }
FORCEINLINE FValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old >> InValue; }); }
FORCEINLINE FValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old >> InValue; }); }
/** Increments the atomic value by one. */
FORCEINLINE ValueType operator++(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic++; }
FORCEINLINE ValueType operator++(int) volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return NativeAtomic++; }
FORCEINLINE FValueType operator++() requires ((CIntegral<T> || CPointer<T>) ) { return ++NativeAtomic; }
FORCEINLINE FValueType operator++() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return ++NativeAtomic; }
/** Increments the atomic value by one. */
FORCEINLINE FValueType operator++(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic++; }
FORCEINLINE FValueType operator++(int) volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return NativeAtomic++; }
/** Decrements the atomic value by one. */
FORCEINLINE ValueType operator--() requires ((CIntegral<T> || CPointer<T>) ) { return --NativeAtomic; }
FORCEINLINE ValueType operator--() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return --NativeAtomic; }
FORCEINLINE FValueType operator--() requires ((CIntegral<T> || CPointer<T>) ) { return --NativeAtomic; }
FORCEINLINE FValueType operator--() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return --NativeAtomic; }
/** Decrements the atomic value by one. */
FORCEINLINE ValueType operator--(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic--; }
FORCEINLINE ValueType operator--(int) volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return NativeAtomic--; }
/** Adds with the atomic value. */
FORCEINLINE ValueType operator+=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic += InValue; }
FORCEINLINE ValueType operator+=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic += InValue; }
FORCEINLINE FValueType operator--(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic--; }
FORCEINLINE FValueType operator--(int) volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return NativeAtomic--; }
/** Adds with the atomic value. */
FORCEINLINE ValueType operator+=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic += InValue; }
FORCEINLINE ValueType operator+=(ptrdiff InValue) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic += InValue; }
FORCEINLINE FValueType operator+=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic += InValue; }
FORCEINLINE FValueType operator+=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic += InValue; }
/** Adds with the atomic value. */
FORCEINLINE FValueType operator+=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic += InValue; }
FORCEINLINE FValueType operator+=(ptrdiff InValue) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic += InValue; }
/** Subtracts with the atomic value. */
FORCEINLINE ValueType operator-=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic -= InValue; }
FORCEINLINE ValueType operator-=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
FORCEINLINE FValueType operator-=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic -= InValue; }
FORCEINLINE FValueType operator-=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
/** Subtracts with the atomic value. */
FORCEINLINE ValueType operator-=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic -= InValue; }
FORCEINLINE ValueType operator-=(ptrdiff InValue) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
FORCEINLINE FValueType operator-=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic -= InValue; }
FORCEINLINE FValueType operator-=(ptrdiff InValue) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
/** Multiples with the atomic value. */
FORCEINLINE ValueType operator*=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchMul(InValue) * InValue; }
FORCEINLINE ValueType operator*=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchMul(InValue) * InValue; }
FORCEINLINE FValueType operator*=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchMul(InValue) * InValue; }
FORCEINLINE FValueType operator*=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchMul(InValue) * InValue; }
/** Divides with the atomic value. */
FORCEINLINE ValueType operator/=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchDiv(InValue) / InValue; }
FORCEINLINE ValueType operator/=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchDiv(InValue) / InValue; }
FORCEINLINE FValueType operator/=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchDiv(InValue) / InValue; }
FORCEINLINE FValueType operator/=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchDiv(InValue) / InValue; }
/** Models with the atomic value. */
FORCEINLINE ValueType operator%=(ValueType InValue) requires (CIntegral<T> ) { return FetchMod(InValue) % InValue; }
FORCEINLINE ValueType operator%=(ValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchMod(InValue) % InValue; }
FORCEINLINE FValueType operator%=(FValueType InValue) requires (CIntegral<T> ) { return FetchMod(InValue) % InValue; }
FORCEINLINE FValueType operator%=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchMod(InValue) % InValue; }
/** Performs bitwise AND with the atomic value. */
FORCEINLINE ValueType operator&=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic &= InValue; }
FORCEINLINE ValueType operator&=(ValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic &= InValue; }
FORCEINLINE FValueType operator&=(FValueType InValue) requires (CIntegral<T> ) { return NativeAtomic &= InValue; }
FORCEINLINE FValueType operator&=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic &= InValue; }
/** Performs bitwise OR with the atomic value. */
FORCEINLINE ValueType operator|=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic |= InValue; }
FORCEINLINE ValueType operator|=(ValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic |= InValue; }
FORCEINLINE FValueType operator|=(FValueType InValue) requires (CIntegral<T> ) { return NativeAtomic |= InValue; }
FORCEINLINE FValueType operator|=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic |= InValue; }
/** Performs bitwise XOR with the atomic value. */
FORCEINLINE ValueType operator^=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic ^= InValue; }
FORCEINLINE ValueType operator^=(ValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic ^= InValue; }
FORCEINLINE FValueType operator^=(FValueType InValue) requires (CIntegral<T> ) { return NativeAtomic ^= InValue; }
FORCEINLINE FValueType operator^=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic ^= InValue; }
/** Performs bitwise LSH with the atomic value. */
FORCEINLINE ValueType operator<<=(size_t InValue) requires (CIntegral<T> ) { return FetchLsh(InValue) << InValue; }
FORCEINLINE ValueType operator<<=(size_t InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchLsh(InValue) << InValue; }
FORCEINLINE FValueType operator<<=(size_t InValue) requires (CIntegral<T> ) { return FetchLsh(InValue) << InValue; }
FORCEINLINE FValueType operator<<=(size_t InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchLsh(InValue) << InValue; }
/** Performs bitwise RSH with the atomic value. */
FORCEINLINE ValueType operator>>=(size_t InValue) requires (CIntegral<T> ) { return FetchRsh(InValue) >> InValue; }
FORCEINLINE ValueType operator>>=(size_t InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchRsh(InValue) >> InValue; }
FORCEINLINE FValueType operator>>=(size_t InValue) requires (CIntegral<T> ) { return FetchRsh(InValue) >> InValue; }
FORCEINLINE FValueType operator>>=(size_t InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchRsh(InValue) >> InValue; }
protected:
NativeAtomicType NativeAtomic;
FNativeAtomic NativeAtomic;
};
@ -311,7 +311,7 @@ struct FAtomicFlag final : FSingleton
public:
/** Constructs an atomic flag. */
FORCEINLINE constexpr FAtomicFlag() : NativeAtomic() { };
FORCEINLINE constexpr FAtomicFlag() = default;
/** Atomically sets flag to false. */
FORCEINLINE void Clear(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.clear(static_cast<NAMESPACE_STD::memory_order>(Order)); }
@ -324,7 +324,7 @@ public:
/** Atomically returns the value of the flag. */
NODISCARD FORCEINLINE bool Test(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.test(static_cast<NAMESPACE_STD::memory_order>(Order)); }
NODISCARD FORCEINLINE bool Test(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.test(static_cast<NAMESPACE_STD::memory_order>(Order)); }
/** Blocks the thread until notified and the atomic value changes. */
FORCEINLINE void Wait(bool Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); const_cast<const NAMESPACE_STD::atomic_flag&>(NativeAtomic).wait(Old, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE void Wait(bool Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); const_cast<const NAMESPACE_STD::atomic_flag&>(NativeAtomic).wait(Old, static_cast<NAMESPACE_STD::memory_order>(Order)); }
@ -332,7 +332,7 @@ public:
/** Notifies at least one or all threads blocked waiting on the atomic object. */
FORCEINLINE void Notify(bool bIsAll = false) { if (bIsAll) const_cast<NAMESPACE_STD::atomic_flag&>(NativeAtomic).notify_all(); else const_cast<NAMESPACE_STD::atomic_flag&>(NativeAtomic).notify_one(); }
FORCEINLINE void Notify(bool bIsAll = false) volatile { if (bIsAll) const_cast<NAMESPACE_STD::atomic_flag&>(NativeAtomic).notify_all(); else const_cast<NAMESPACE_STD::atomic_flag&>(NativeAtomic).notify_one(); }
private:
NAMESPACE_STD::atomic_flag NativeAtomic;

View File

@ -262,29 +262,29 @@ public:
{
Callable = InCallable;
using DecayedType = TDecay<T>;
using FDecayedType = TDecay<T>;
static constexpr const FRTTI SelectedRTTI(InPlaceType<DecayedType>);
static constexpr const FRTTI SelectedRTTI(InPlaceType<FDecayedType>);
RTTI = reinterpret_cast<uintptr>(&SelectedRTTI);
if constexpr (CEmpty<DecayedType> && CTrivial<DecayedType>) return; // ERepresentation::Empty
if constexpr (CEmpty<FDecayedType> && CTrivial<FDecayedType>) return; // ERepresentation::Empty
constexpr bool bIsTriviallyStorable = sizeof(DecayedType) <= sizeof(InternalStorage) && alignof(DecayedType) <= alignof(TFunctionStorage) && CTriviallyCopyable<DecayedType>;
constexpr bool bIsSmallStorable = sizeof(DecayedType) <= sizeof(InternalStorage) && alignof(DecayedType) <= alignof(TFunctionStorage);
constexpr bool bIsTriviallyStorable = sizeof(FDecayedType) <= sizeof(InternalStorage) && alignof(FDecayedType) <= alignof(TFunctionStorage) && CTriviallyCopyable<FDecayedType>;
constexpr bool bIsSmallStorable = sizeof(FDecayedType) <= sizeof(InternalStorage) && alignof(FDecayedType) <= alignof(TFunctionStorage);
if constexpr (bIsTriviallyStorable)
{
new (&InternalStorage) DecayedType(Forward<Ts>(Args)...);
new (&InternalStorage) FDecayedType(Forward<Ts>(Args)...);
RTTI |= static_cast<uintptr>(ERepresentation::Trivial);
}
else if constexpr (bIsSmallStorable)
{
new (&InternalStorage) DecayedType(Forward<Ts>(Args)...);
new (&InternalStorage) FDecayedType(Forward<Ts>(Args)...);
RTTI |= static_cast<uintptr>(ERepresentation::Small);
}
else
{
ExternalStorage = new DecayedType(Forward<Ts>(Args)...);
ExternalStorage = new FDecayedType(Forward<Ts>(Args)...);
RTTI |= static_cast<uintptr>(ERepresentation::Big);
}
@ -446,12 +446,12 @@ template <typename Ret, typename... Ts, typename F> struct TIsInvocableSignature
template <typename Ret, typename... Ts, typename F> struct TIsInvocableSignature<Ret(Ts...) const&&, F> : TBoolConstant<CInvocableResult<Ret, const F , Ts...>> { };
template <typename F> struct TFunctionInfo;
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) > { using Fn = Ret(Ts...); using CVRef = int; };
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) & > { using Fn = Ret(Ts...); using CVRef = int&; };
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) && > { using Fn = Ret(Ts...); using CVRef = int&&; };
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const > { using Fn = Ret(Ts...); using CVRef = const int; };
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const& > { using Fn = Ret(Ts...); using CVRef = const int&; };
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const&&> { using Fn = Ret(Ts...); using CVRef = const int&&; };
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) > { using FFn = Ret(Ts...); using FCVRef = int; };
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) & > { using FFn = Ret(Ts...); using FCVRef = int&; };
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) && > { using FFn = Ret(Ts...); using FCVRef = int&&; };
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const > { using FFn = Ret(Ts...); using FCVRef = const int; };
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const& > { using FFn = Ret(Ts...); using FCVRef = const int&; };
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const&&> { using FFn = Ret(Ts...); using FCVRef = const int&&; };
template <typename F, typename CVRef, bool bIsRef, bool bIsUnique = false> class TFunctionImpl;
@ -460,8 +460,8 @@ class TFunctionImpl<Ret(Ts...), CVRef, bIsRef, bIsUnique>
{
public:
using ResultType = Ret;
using ArgumentType = TTypeSequence<Ts...>;
using FResultType = Ret;
using FArgumentType = TTypeSequence<Ts...>;
FORCEINLINE constexpr TFunctionImpl() = default;
FORCEINLINE constexpr TFunctionImpl(const TFunctionImpl&) = default;
@ -471,12 +471,12 @@ public:
FORCEINLINE constexpr ~TFunctionImpl() = default;
/** Invokes the stored callable function target with the parameters args. */
FORCEINLINE ResultType operator()(Ts... Args) requires (CSameAs<CVRef, int >) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE ResultType operator()(Ts... Args) & requires (CSameAs<CVRef, int& >) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE ResultType operator()(Ts... Args) && requires (CSameAs<CVRef, int&&>) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE ResultType operator()(Ts... Args) const requires (CSameAs<CVRef, const int >) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE ResultType operator()(Ts... Args) const& requires (CSameAs<CVRef, const int& >) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE ResultType operator()(Ts... Args) const&& requires (CSameAs<CVRef, const int&&>) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE FResultType operator()(Ts... Args) requires (CSameAs<CVRef, int >) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE FResultType operator()(Ts... Args) & requires (CSameAs<CVRef, int& >) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE FResultType operator()(Ts... Args) && requires (CSameAs<CVRef, int&&>) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE FResultType operator()(Ts... Args) const requires (CSameAs<CVRef, const int >) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE FResultType operator()(Ts... Args) const& requires (CSameAs<CVRef, const int& >) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE FResultType operator()(Ts... Args) const&& requires (CSameAs<CVRef, const int&&>) { return CallImpl(Forward<Ts>(Args)...); }
/** @return false if instance stores a callable function target, true otherwise. */
NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& requires (!bIsRef) { return !IsValid(); }
@ -487,14 +487,14 @@ public:
private:
using CallableType = ResultType(*)(uintptr, Ts&&...);
using FCallableType = FResultType(*)(uintptr, Ts&&...);
TFunctionStorage<bIsRef, bIsUnique> Storage;
FORCEINLINE ResultType CallImpl(Ts&&... Args) const
FORCEINLINE FResultType CallImpl(Ts&&... Args) const
{
checkf(Storage.IsValid(), TEXT("Attempting to call an unbound TFunction!"));
CallableType Callable = reinterpret_cast<CallableType>(Storage.GetCallable());
FCallableType Callable = reinterpret_cast<FCallableType>(Storage.GetCallable());
return Callable(Storage.GetValuePtr(), Forward<Ts>(Args)...);
}
@ -510,26 +510,26 @@ protected:
template <typename T, typename... Us>
FORCEINLINE constexpr TDecay<T>& Emplace(Us&&... Args)
{
using DecayedType = TDecay<T>;
using FDecayedType = TDecay<T>;
// This add a l-value reference to a non-reference type, while preserving the r-value reference.
using ObjectType = TCopyCVRef<CVRef, DecayedType>;
using InvokeType = TConditional<CReference<ObjectType>, ObjectType, ObjectType&>;
using FObjectType = TCopyCVRef<CVRef, FDecayedType>;
using FInvokeType = TConditional<CReference<FObjectType>, FObjectType, FObjectType&>;
CallableType Callable = [](uintptr ObjectPtr, Ts&&... Args) -> ResultType
FCallableType Callable = [](uintptr ObjectPtr, Ts&&... Args) -> FResultType
{
return InvokeResult<ResultType>(
static_cast<InvokeType>(*reinterpret_cast<DecayedType*>(ObjectPtr)),
return InvokeResult<FResultType>(
static_cast<FInvokeType>(*reinterpret_cast<FDecayedType*>(ObjectPtr)),
Forward<Ts>(Args)...
);
};
Storage.template Emplace<DecayedType>(
Storage.template Emplace<FDecayedType>(
reinterpret_cast<uintptr>(Callable),
Forward<Us>(Args)...
);
return *reinterpret_cast<DecayedType*>(Storage.GetValuePtr());
return *reinterpret_cast<FDecayedType*>(Storage.GetValuePtr());
}
friend FORCEINLINE constexpr void Swap(TFunctionImpl& A, TFunctionImpl& B) requires (!bIsRef) { Swap(A.Storage, B.Storage); }
@ -552,15 +552,15 @@ NAMESPACE_PRIVATE_END
template <CFunction F>
class TFunctionRef final
: public NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
true>
{
private:
using Impl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
using FImpl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
true>;
public:
@ -585,7 +585,7 @@ public:
FORCEINLINE constexpr TFunctionRef(T&& InValue)
{
checkf(NAMESPACE_PRIVATE::FunctionIsBound(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef"));
Impl::template Emplace<T>(Forward<T>(InValue));
FImpl::template Emplace<T>(Forward<T>(InValue));
}
template <typename T>
@ -602,21 +602,21 @@ public:
template <CFunction F>
class TFunction final
: public NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
false, false>
{
private:
using Impl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
using FImpl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
false, false>;
public:
/** Default constructor. */
FORCEINLINE constexpr TFunction(nullptr_t = nullptr) { Impl::Invalidate(); }
FORCEINLINE constexpr TFunction(nullptr_t = nullptr) { FImpl::Invalidate(); }
FORCEINLINE TFunction(const TFunction&) = default;
FORCEINLINE TFunction(TFunction&&) = default;
@ -634,8 +634,8 @@ public:
&& NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value)
FORCEINLINE TFunction(T&& InValue)
{
if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Impl::Invalidate();
else Impl::template Emplace<T>(Forward<T>(InValue));
if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) FImpl::Invalidate();
else FImpl::template Emplace<T>(Forward<T>(InValue));
}
/**
@ -647,7 +647,7 @@ public:
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE explicit TFunction(TInPlaceType<T>, Ts&&... Args)
{
Impl::template Emplace<T>(Forward<Ts>(Args)...);
FImpl::template Emplace<T>(Forward<Ts>(Args)...);
}
/**
@ -659,7 +659,7 @@ public:
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE explicit TFunction(TInPlaceType<T>, initializer_list<U> IL, Ts&&... Args)
{
Impl::template Emplace<T>(IL, Forward<Ts>(Args)...);
FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...);
}
/** Removes any bound callable from the TFunction, restoring it to the default empty state. */
@ -692,8 +692,8 @@ public:
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE TDecay<T>& Emplace(Ts&&... Args)
{
Impl::Destroy();
return Impl::template Emplace<T>(Forward<Ts>(Args)...);
FImpl::Destroy();
return FImpl::template Emplace<T>(Forward<Ts>(Args)...);
}
/**
@ -710,15 +710,15 @@ public:
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE TDecay<T>& Emplace(initializer_list<U> IL, Ts&&... Args)
{
Impl::Destroy();
return Impl::template Emplace<T>(IL, Forward<Ts>(Args)...);
FImpl::Destroy();
return FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...);
}
/** Removes any bound callable from the TFunction, restoring it to the default empty state. */
FORCEINLINE constexpr void Reset() { Impl::Destroy(); Impl::Invalidate(); }
FORCEINLINE constexpr void Reset() { FImpl::Destroy(); FImpl::Invalidate(); }
/** Overloads the Swap algorithm for TFunction. */
friend FORCEINLINE constexpr void Swap(TFunction& A, TFunction& B) { Swap(static_cast<Impl&>(A), static_cast<Impl&>(B)); }
friend FORCEINLINE constexpr void Swap(TFunction& A, TFunction& B) { Swap(static_cast<FImpl&>(A), static_cast<FImpl&>(B)); }
};
@ -731,21 +731,21 @@ public:
template <CFunction F>
class TUniqueFunction final
: public NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
false, true>
{
private:
using Impl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
using FImpl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
false, true>;
public:
/** Default constructor. */
FORCEINLINE constexpr TUniqueFunction(nullptr_t = nullptr) { Impl::Invalidate(); }
FORCEINLINE constexpr TUniqueFunction(nullptr_t = nullptr) { FImpl::Invalidate(); }
FORCEINLINE TUniqueFunction(const TUniqueFunction&) = delete;
FORCEINLINE TUniqueFunction(TUniqueFunction&&) = default;
@ -788,8 +788,8 @@ public:
&& NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value)
FORCEINLINE TUniqueFunction(T&& InValue)
{
if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Impl::Invalidate();
else Impl::template Emplace<T>(Forward<T>(InValue));
if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) FImpl::Invalidate();
else FImpl::template Emplace<T>(Forward<T>(InValue));
}
/**
@ -800,7 +800,7 @@ public:
&& CConstructibleFrom<TDecay<T>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE explicit TUniqueFunction(TInPlaceType<T>, Ts&&... Args)
{
Impl::template Emplace<T>(Forward<Ts>(Args)...);
FImpl::template Emplace<T>(Forward<Ts>(Args)...);
}
/**
@ -811,11 +811,11 @@ public:
&& CConstructibleFrom<TDecay<T>, initializer_list<U>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE explicit TUniqueFunction(TInPlaceType<T>, initializer_list<U> IL, Ts&&... Args)
{
Impl::template Emplace<T>(IL, Forward<Ts>(Args)...);
FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...);
}
/** Removes any bound callable from the TUniqueFunction, restoring it to the default empty state. */
FORCEINLINE constexpr TUniqueFunction& operator=(nullptr_t) { Impl::Destroy(); Impl::Invalidate(); return *this; }
FORCEINLINE constexpr TUniqueFunction& operator=(nullptr_t) { FImpl::Destroy(); FImpl::Invalidate(); return *this; }
template <typename T> requires (NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value
&& !CTFunctionRef<TDecay<T>> && !CTFunction<TDecay<T>> && !CTUniqueFunction<TDecay<T>>
@ -841,9 +841,9 @@ public:
&& CConstructibleFrom<TDecay<T>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE TDecay<T>& Emplace(Ts&&... Args)
{
Impl::Destroy();
using DecayedType = TDecay<T>;
return Impl::template Emplace<T>(Forward<Ts>(Args)...);
FImpl::Destroy();
return FImpl::template Emplace<T>(Forward<Ts>(Args)...);
}
/**
@ -859,16 +859,16 @@ public:
&& CConstructibleFrom<TDecay<T>, initializer_list<U>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE TDecay<T>& Emplace(initializer_list<U> IL, Ts&&... Args)
{
Impl::Destroy();
using DecayedType = TDecay<T>;
return Impl::template Emplace<T>(IL, Forward<Ts>(Args)...);
FImpl::Destroy();
return FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...);
}
/** Removes any bound callable from the TUniqueFunction, restoring it to the default empty state. */
FORCEINLINE constexpr void Reset() { Impl::Destroy(); Impl::Invalidate(); }
FORCEINLINE constexpr void Reset() { FImpl::Destroy(); FImpl::Invalidate(); }
/** Overloads the Swap algorithm for TUniqueFunction. */
friend FORCEINLINE constexpr void Swap(TUniqueFunction& A, TUniqueFunction& B) { Swap(static_cast<Impl&>(A), static_cast<Impl&>(B)); }
friend FORCEINLINE constexpr void Swap(TUniqueFunction& A, TUniqueFunction& B) { Swap(static_cast<FImpl&>(A), static_cast<FImpl&>(B)); }
};

View File

@ -10,7 +10,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_PRIVATE_BEGIN
struct InvokeFunction
struct FInvokeFunction
{
template <typename F, typename... Ts>
static auto Invoke(F&& Object, Ts&&... Args)
@ -20,7 +20,7 @@ struct InvokeFunction
}
};
struct InvokeMemberFunction
struct FInvokeMemberFunction
{
template <typename F, typename ObjectType, typename... Ts>
static auto Invoke(F&& Func, ObjectType&& Object, Ts&&... Args)
@ -37,7 +37,7 @@ struct InvokeMemberFunction
}
};
struct InvokeMemberObject
struct FInvokeMemberObject
{
template <typename F, typename ObjectType>
static auto Invoke(F&& Func, ObjectType&& Object)
@ -59,34 +59,34 @@ template <typename F,
typename Decayed = TDecay<F>,
bool IsMemberFunction = CMemberFunctionPointer<Decayed>,
bool IsMemberObject = CMemberObjectPointer<Decayed>>
struct InvokeMember;
struct FInvokeMember;
template <typename F, typename T, typename Decayed>
struct InvokeMember<F, T, Decayed, true, false> : InvokeMemberFunction { };
struct FInvokeMember<F, T, Decayed, true, false> : FInvokeMemberFunction { };
template <typename F, typename T, typename Decayed>
struct InvokeMember<F, T, Decayed, false, true> : InvokeMemberObject { };
struct FInvokeMember<F, T, Decayed, false, true> : FInvokeMemberObject { };
template <typename F, typename T, typename Decayed>
struct InvokeMember<F, T, Decayed, false, false> : InvokeFunction { };
struct FInvokeMember<F, T, Decayed, false, false> : FInvokeFunction { };
template <typename F, typename... Ts>
struct InvokeImpl;
struct FInvokeImpl;
template <typename F>
struct InvokeImpl<F> : InvokeFunction { };
struct FInvokeImpl<F> : FInvokeFunction { };
template <typename F, typename T, typename... Ts>
struct InvokeImpl<F, T, Ts...> : InvokeMember<F, T> { };
struct FInvokeImpl<F, T, Ts...> : FInvokeMember<F, T> { };
NAMESPACE_PRIVATE_END
/** Invoke the Callable object f with the parameters args. */
template <typename F, typename... Ts> requires (CInvocable<F, Ts...>)
FORCEINLINE constexpr auto Invoke(F&& Func, Ts&&... Args)
-> decltype(NAMESPACE_PRIVATE::InvokeImpl<F, Ts...>::Invoke(Forward<F>(Func), Forward<Ts>(Args)...))
-> decltype(NAMESPACE_PRIVATE::FInvokeImpl<F, Ts...>::Invoke(Forward<F>(Func), Forward<Ts>(Args)...))
{
return NAMESPACE_PRIVATE::InvokeImpl<F, Ts...>::Invoke(Forward<F>(Func), Forward<Ts>(Args)...);
return NAMESPACE_PRIVATE::FInvokeImpl<F, Ts...>::Invoke(Forward<F>(Func), Forward<Ts>(Args)...);
}
/** Invoke the Callable object f with the parameters args. */

View File

@ -12,7 +12,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
template <typename T, T... Ints>
struct TIntegerSequence
{
using ValueType = T;
using FValueType = T;
FORCEINLINE static constexpr size_t Num() { return sizeof...(Ints); }
FORCEINLINE static constexpr const T* GetData() { return NAMESPACE_REDCRAFT::GetData({ Ints... }); }
};
@ -24,7 +24,7 @@ NAMESPACE_PRIVATE_BEGIN
template <unsigned N, typename T>
struct TMakeIntegerSequenceImpl
{
using Type = typename __make_integer_seq<TIntegerSequence, T, N>;
using FType = typename __make_integer_seq<TIntegerSequence, T, N>;
};
#elif __has_builtin(__make_integer_seq)
@ -32,7 +32,7 @@ struct TMakeIntegerSequenceImpl
template <unsigned N, typename T>
struct TMakeIntegerSequenceImpl
{
using Type = typename __make_integer_seq<TIntegerSequence, T, N>;
using FType = typename __make_integer_seq<TIntegerSequence, T, N>;
};
#else
@ -40,13 +40,13 @@ struct TMakeIntegerSequenceImpl
template <unsigned N, typename T, T... Ints>
struct TMakeIntegerSequenceImpl
{
using Type = typename TMakeIntegerSequenceImpl<N - 1, T, T(N - 1), Ints...>::Type;
using FType = typename TMakeIntegerSequenceImpl<N - 1, T, T(N - 1), Ints...>::FType;
};
template <typename T, T... Ints>
struct TMakeIntegerSequenceImpl<0, T, Ints...>
{
using Type = TIntegerSequence<T, Ints...>;
using FType = TIntegerSequence<T, Ints...>;
};
#endif
@ -57,7 +57,7 @@ template <size_t... Ints>
using TIndexSequence = TIntegerSequence<size_t, Ints...>;
template <typename T, T N>
using TMakeIntegerSequence = typename NAMESPACE_PRIVATE::TMakeIntegerSequenceImpl<N, T>::Type;
using TMakeIntegerSequence = typename NAMESPACE_PRIVATE::TMakeIntegerSequenceImpl<N, T>::FType;
template <size_t N>
using TMakeIndexSequence = TMakeIntegerSequence<size_t, N>;
@ -103,7 +103,7 @@ struct TFrontImpl;
template <typename T, typename... Ts>
struct TFrontImpl<TTypeSequence<T, Ts...>>
{
using Type = T;
using FType = T;
};
template <typename TSequence>
@ -112,7 +112,7 @@ struct TPopImpl;
template <typename T, typename... Ts>
struct TPopImpl<TTypeSequence<T, Ts...>>
{
using Type = TTypeSequence<Ts...>;
using FType = TTypeSequence<Ts...>;
};
template <typename T, typename TSequence>
@ -121,19 +121,19 @@ struct TPushImpl;
template <typename T, typename... Ts>
struct TPushImpl<T, TTypeSequence<Ts...>>
{
using Type = TTypeSequence<T, Ts...>;
using FType = TTypeSequence<T, Ts...>;
};
NAMESPACE_PRIVATE_END
template <CTTypeSequence TSequence>
using TFront = typename NAMESPACE_PRIVATE::TFrontImpl<TSequence>::Type;
using TFront = typename NAMESPACE_PRIVATE::TFrontImpl<TSequence>::FType;
template <CTTypeSequence TSequence>
using TPop = typename NAMESPACE_PRIVATE::TPopImpl<TSequence>::Type;
using TPop = typename NAMESPACE_PRIVATE::TPopImpl<TSequence>::FType;
template <typename T, typename TSequence>
using TPush = typename NAMESPACE_PRIVATE::TPushImpl<T, TSequence>::Type;
using TPush = typename NAMESPACE_PRIVATE::TPushImpl<T, TSequence>::FType;
NAMESPACE_PRIVATE_BEGIN
@ -194,19 +194,19 @@ struct TIndexAssert
template <size_t I, typename TSequence>
struct TTypeImpl
{
using Type = typename TTypeImpl<I - 1, TPop<TSequence>>::Type;
using FType = typename TTypeImpl<I - 1, TPop<TSequence>>::FType;
};
template <typename TSequence>
struct TTypeImpl<0, TSequence>
{
using Type = TFront<TSequence>;
using FType = TFront<TSequence>;
};
template <typename TSequence>
struct TTypeImpl<INDEX_NONE, TSequence>
{
using Type = void;
using FType = void;
};
template <size_t I, typename TSequence>
@ -214,7 +214,7 @@ struct TTypeAssert
{
static_assert(I < TSizeImpl<TSequence>::Value, "I is invalid index in type sequence");
static constexpr size_t SafeIndex = I < TSizeImpl<TSequence>::Value ? I : INDEX_NONE;
using Type = TCopyCV<TSequence, typename TTypeImpl<SafeIndex, TSequence>::Type>;
using FType = TCopyCV<TSequence, typename TTypeImpl<SafeIndex, TSequence>::FType>;
};
NAMESPACE_PRIVATE_END
@ -226,29 +226,29 @@ template <typename T, CTTypeSequence TSequence>
inline constexpr size_t TIndex = NAMESPACE_PRIVATE::TIndexAssert<T, TSequence>::Value;
template <size_t I, CTTypeSequence TSequence>
using TType = typename NAMESPACE_PRIVATE::TTypeAssert<I, TSequence>::Type;
using TType = typename NAMESPACE_PRIVATE::TTypeAssert<I, TSequence>::FType;
NAMESPACE_PRIVATE_BEGIN
template <typename TSequence>
struct TUniqueTypeSequenceImpl
{
using FrontType = TFront<TSequence>;
using NextSequence = TPop<TSequence>;
using NextUniqueSequence = typename TUniqueTypeSequenceImpl<NextSequence>::Type;
using Type = TConditional<!CExistentType<FrontType, NextSequence>, TPush<FrontType, NextUniqueSequence>, NextUniqueSequence>;
using FFrontType = TFront<TSequence>;
using FNextSequence = TPop<TSequence>;
using FNextUniqueSequence = typename TUniqueTypeSequenceImpl<FNextSequence>::FType;
using FType = TConditional<!CExistentType<FFrontType, FNextSequence>, TPush<FFrontType, FNextUniqueSequence>, FNextUniqueSequence>;
};
template <>
struct TUniqueTypeSequenceImpl<TTypeSequence<>>
{
using Type = TTypeSequence<>;
using FType = TTypeSequence<>;
};
NAMESPACE_PRIVATE_END
template <CTTypeSequence TSequence>
using TUniqueTypeSequence = typename NAMESPACE_PRIVATE::TUniqueTypeSequenceImpl<TSequence>::Type;
using TUniqueTypeSequence = typename NAMESPACE_PRIVATE::TUniqueTypeSequenceImpl<TSequence>::FType;
NAMESPACE_PRIVATE_BEGIN

View File

@ -45,9 +45,9 @@ class TOptional<T, false> final
{
public:
using ValueType = T;
using FValueType = T;
static_assert(!CReference<ValueType>);
static_assert(!CReference<FValueType>);
/** Constructs an object that does not contain a value. */
FORCEINLINE constexpr TOptional() : bIsValid(false) { }
@ -67,7 +67,7 @@ public:
FORCEINLINE constexpr explicit TOptional(FInPlace, Ts&&... Args)
: bIsValid(true)
{
new (&Value) ValueType(Forward<Ts>(Args)...);
new (&Value) FValueType(Forward<Ts>(Args)...);
}
/** Constructs an object with initial content an object, direct-non-list-initialized from IL, Forward<Ts>(Args).... */
@ -75,7 +75,7 @@ public:
FORCEINLINE constexpr explicit TOptional(FInPlace, initializer_list<W> IL, Ts&&... Args)
: bIsValid(true)
{
new (&Value) ValueType(IL, Forward<Ts>(Args)...);
new (&Value) FValueType(IL, Forward<Ts>(Args)...);
}
/** Copies content of other into a new instance. */
@ -85,7 +85,7 @@ public:
FORCEINLINE constexpr TOptional(const TOptional& InValue) requires (CCopyConstructible<T> && !CTriviallyCopyConstructible<T>)
: bIsValid(InValue.IsValid())
{
if (InValue.IsValid()) new (&Value) ValueType(InValue.GetValue());
if (InValue.IsValid()) new (&Value) FValueType(InValue.GetValue());
}
/** Moves content of other into a new instance. */
@ -95,7 +95,7 @@ public:
FORCEINLINE constexpr TOptional(TOptional&& InValue) requires (CMoveConstructible<T> && !CTriviallyMoveConstructible<T>)
: bIsValid(InValue.IsValid())
{
if (InValue.IsValid()) new (&Value) ValueType(MoveTemp(InValue.GetValue()));
if (InValue.IsValid()) new (&Value) FValueType(MoveTemp(InValue.GetValue()));
}
/** Converting copy constructor. */
@ -103,7 +103,7 @@ public:
FORCEINLINE constexpr explicit (!CConvertibleTo<const U&, T>) TOptional(const TOptional<U>& InValue)
: bIsValid(InValue.IsValid())
{
if (InValue.IsValid()) new (&Value) ValueType(InValue.GetValue());
if (InValue.IsValid()) new (&Value) FValueType(InValue.GetValue());
}
/** Converting move constructor. */
@ -111,7 +111,7 @@ public:
FORCEINLINE constexpr explicit (!CConvertibleTo<U&&, T>) TOptional(TOptional<U>&& InValue)
: bIsValid(InValue.IsValid())
{
if (InValue.IsValid()) new (&Value) ValueType(MoveTemp(InValue.GetValue()));
if (InValue.IsValid()) new (&Value) FValueType(MoveTemp(InValue.GetValue()));
}
/** Destroys the contained object, if any, as if by a call to Reset(). */
@ -141,7 +141,7 @@ public:
if (IsValid()) GetValue() = InValue.GetValue();
else
{
new (&Value) ValueType(InValue.GetValue());
new (&Value) FValueType(InValue.GetValue());
bIsValid = true;
}
@ -166,7 +166,7 @@ public:
if (IsValid()) GetValue() = MoveTemp(InValue.GetValue());
else
{
new (&Value) ValueType(MoveTemp(InValue.GetValue()));
new (&Value) FValueType(MoveTemp(InValue.GetValue()));
bIsValid = true;
}
@ -187,7 +187,7 @@ public:
if (IsValid()) GetValue() = InValue.GetValue();
else
{
new (&Value) ValueType(InValue.GetValue());
new (&Value) FValueType(InValue.GetValue());
bIsValid = true;
}
@ -208,7 +208,7 @@ public:
if (IsValid()) GetValue() = MoveTemp(InValue.GetValue());
else
{
new (&Value) ValueType(MoveTemp(InValue.GetValue()));
new (&Value) FValueType(MoveTemp(InValue.GetValue()));
bIsValid = true;
}
@ -222,7 +222,7 @@ public:
if (IsValid()) GetValue() = Forward<U>(InValue);
else
{
new (&Value) ValueType(Forward<U>(InValue));
new (&Value) FValueType(Forward<U>(InValue));
bIsValid = true;
}
@ -278,7 +278,7 @@ public:
{
Reset();
T* Result = new (&Value) ValueType(Forward<Ts>(Args)...);
T* Result = new (&Value) FValueType(Forward<Ts>(Args)...);
bIsValid = true;
return *Result;
@ -298,7 +298,7 @@ public:
{
Reset();
T* Result = new (&Value) ValueType(IL, Forward<Ts>(Args)...);
T* Result = new (&Value) FValueType(IL, Forward<Ts>(Args)...);
bIsValid = true;
return *Result;
@ -335,7 +335,7 @@ public:
{
bIsValid = false;
reinterpret_cast<T*>(&Value)->~ValueType();
reinterpret_cast<T*>(&Value)->~FValueType();
}
}
@ -380,9 +380,9 @@ class TOptional<T, true> final
{
public:
using ValueType = TRemoveReference<T>;
using FValueType = TRemoveReference<T>;
static_assert(!CReference<ValueType>);
static_assert(!CReference<FValueType>);
/** Constructs an object that does not contain a reference. */
FORCEINLINE constexpr TOptional() : Ptr(nullptr) { }
@ -408,13 +408,13 @@ public:
{ }
/** Converting constructor. */
template <typename U> requires (!CConst<ValueType> && CConstructibleFrom<T, U&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<U, T>)
template <typename U> requires (!CConst<FValueType> && CConstructibleFrom<T, U&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<U, T>)
FORCEINLINE constexpr explicit (!CConvertibleTo<U&, T>) TOptional(TOptional<U, false>& InValue)
: Ptr(InValue.IsValid() ? AddressOf(static_cast<T>(InValue.GetValue())) : nullptr)
{ }
/** Converting constructor. */
template <typename U> requires (CConst<ValueType> && CConstructibleFrom<T, const U&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<U, T>)
template <typename U> requires (CConst<FValueType> && CConstructibleFrom<T, const U&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<U, T>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const U&, T>) TOptional(const TOptional<U, false>& InValue)
: Ptr(InValue.IsValid() ? AddressOf(static_cast<T>(InValue.GetValue())) : nullptr)
{ }
@ -492,7 +492,7 @@ public:
private:
ValueType* Ptr;
FValueType* Ptr;
};

View File

@ -24,7 +24,7 @@ template <typename T>
concept CTPropagateConst = NAMESPACE_PRIVATE::TIsTPropagateConst<TRemoveCV<T>>::Value;
/**
* TPropagateConst is a const-propagating wrapper for pointers and pointer-like objects.
* 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)
@ -32,7 +32,7 @@ class TPropagateConst final
{
public:
using ElementType = TPointerTraits<T>::ElementType;
using FElementType = TPointerTraits<T>::FElementType;
/** Constructs an TPropagateConst, default-initializing underlying pointer. */
FORCEINLINE constexpr TPropagateConst() = default;
@ -105,26 +105,26 @@ public:
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); }
NODISCARD FORCEINLINE constexpr FElementType* Get() { return TPointerTraits<T>::ToAddress(Ptr); }
NODISCARD FORCEINLINE constexpr const FElementType* 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(); }
NODISCARD FORCEINLINE constexpr FElementType& operator*() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); }
NODISCARD FORCEINLINE constexpr const FElementType& operator*() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); }
NODISCARD FORCEINLINE constexpr FElementType* operator->() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); }
NODISCARD FORCEINLINE constexpr const FElementType* 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; }
NODISCARD FORCEINLINE constexpr operator FElementType*() requires (CConvertibleTo<T, FElementType*>) { return Ptr; }
NODISCARD FORCEINLINE constexpr operator const FElementType*() const requires (CConvertibleTo<T, FElementType*>) { return Ptr; }
/** @return The reference to the pointer-like object stored. */
NODISCARD FORCEINLINE constexpr T& GetUnderlying() { return Ptr; }

View File

@ -22,7 +22,7 @@ class TReferenceWrapper final
{
public:
using Type = ReferencedType;
using FType = ReferencedType;
/** Constructs a new reference wrapper. */
template <typename T = ReferencedType&> requires (CConvertibleTo<T&&, ReferencedType&> && !CSameAs<TReferenceWrapper, TRemoveCVRef<T>>)
@ -111,10 +111,10 @@ NAMESPACE_PRIVATE_BEGIN
template <typename T> struct TIsTReferenceWrapperImpl : FFalse { };
template <typename T> struct TIsTReferenceWrapperImpl<TReferenceWrapper<T>> : FTrue { };
template <typename T> struct TUnwrapReferenceImpl { using Type = T; };
template <typename T> struct TUnwrapReferenceImpl<TReferenceWrapper<T>> { using Type = T&; };
template <typename T> struct TUnwrapReferenceImpl { using FType = T; };
template <typename T> struct TUnwrapReferenceImpl<TReferenceWrapper<T>> { using FType = T&; };
template <typename T> struct TUnwrapRefDecayImpl { using Type = typename TUnwrapReferenceImpl<TDecay<T>>::Type; };
template <typename T> struct TUnwrapRefDecayImpl { using FType = typename TUnwrapReferenceImpl<TDecay<T>>::FType; };
NAMESPACE_PRIVATE_END
@ -122,10 +122,10 @@ template <typename T>
concept CTReferenceWrapper = NAMESPACE_PRIVATE::TIsTReferenceWrapperImpl<TRemoveCV<T>>::Value;
template <typename T>
using TUnwrapReference = typename NAMESPACE_PRIVATE::TUnwrapReferenceImpl<T>::Type;
using TUnwrapReference = typename NAMESPACE_PRIVATE::TUnwrapReferenceImpl<T>::FType;
template <typename T>
using TUnwrapRefDecay = typename NAMESPACE_PRIVATE::TUnwrapRefDecayImpl<T>::Type;
using TUnwrapRefDecay = typename NAMESPACE_PRIVATE::TUnwrapRefDecayImpl<T>::FType;
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)

View File

@ -49,7 +49,7 @@ struct TTupleElementImpl;
template <size_t I, typename... Ts>
struct TTupleElementImpl<I, TTuple<Ts...>>
{
using Type = Meta::TType<I, TTypeSequence<Ts...>>;
using FType = Meta::TType<I, TTypeSequence<Ts...>>;
};
template <bool bTrue, typename... Ts>
@ -77,12 +77,12 @@ struct TTupleBasicElement
{
private:
using ValueType = T;
ValueType Value;
using FValueType = T;
FValueType Value;
public:
template <typename Type>
template <typename Type> requires (CConstructibleFrom<T, Type&&>)
FORCEINLINE constexpr TTupleBasicElement(Type&& Arg)
: Value(Forward<Type>(Arg))
{ }
@ -110,10 +110,10 @@ public:
template <typename T> \
struct TTupleBasicElement<T, Index> \
{ \
using Name##Type = T; \
Name##Type Name; \
using F##Name##Type = T; \
F##Name##Type Name; \
\
template <typename Type> \
template <typename Type> requires (CConstructibleFrom<T, F##Name##Type&&>) \
FORCEINLINE constexpr TTupleBasicElement(Type&& Arg) \
: Name(Forward<Type>(Arg)) \
{ } \
@ -315,15 +315,15 @@ template <typename T, CTTuple U>
inline constexpr size_t TTupleIndex = NAMESPACE_PRIVATE::TTupleIndexImpl<T, TRemoveCV<U>>::Value;
template <size_t I, CTTuple U>
using TTupleElement = TCopyCV<U, typename NAMESPACE_PRIVATE::TTupleElementImpl<I, TRemoveCV<U>>::Type>;
using TTupleElement = TCopyCV<U, typename NAMESPACE_PRIVATE::TTupleElementImpl<I, TRemoveCV<U>>::FType>;
template <typename... Ts>
class TTuple final : public NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>
{
private:
using Super = NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>;
using Helper = NAMESPACE_PRIVATE::TTupleHelper<TIndexSequenceFor<Ts...>>;
using FSuper = NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>;
using FHelper = NAMESPACE_PRIVATE::TTupleHelper<TIndexSequenceFor<Ts...>>;
public:
@ -334,7 +334,7 @@ public:
template <typename... Us> requires (sizeof...(Ts) >= 1 && sizeof...(Us) == sizeof...(Ts))
&& (true && ... && CConstructibleFrom<Ts, Us&&>)
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(Us&&... Args)
: Super(NAMESPACE_PRIVATE::ForwardingConstructor, Forward<Us>(Args)...)
: FSuper(NAMESPACE_PRIVATE::ForwardingConstructor, Forward<Us>(Args)...)
{ }
/** Converting copy constructor. Initializes each element of the tuple with the corresponding element of other. */
@ -342,7 +342,7 @@ public:
&& (true && ... && CConstructibleFrom<Ts, const Us&>)
&& NAMESPACE_PRIVATE::TTupleConvertCopy<sizeof...(Ts) != 1, Ts..., Us...>::Value)
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(const TTuple<Us...>& InValue)
: Super(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue)
: FSuper(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue)
{ }
/** Converting move constructor. Initializes each element of the tuple with the corresponding element of other. */
@ -350,7 +350,7 @@ public:
&& (true && ... && CConstructibleFrom<Ts, Us&&>)
&& NAMESPACE_PRIVATE::TTupleConvertMove<sizeof...(Ts) != 1, Ts..., Us...>::Value)
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(TTuple<Us...>&& InValue)
: Super(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue))
: FSuper(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue))
{ }
/** Copies/moves content of other into a new instance. */
@ -362,7 +362,7 @@ public:
&& (true && ... && CAssignableFrom<Ts&, const Us&>))
FORCEINLINE constexpr TTuple& operator=(const TTuple<Us...>& InValue)
{
Helper::Assign(*this, InValue);
FHelper::Assign(*this, InValue);
return *this;
}
@ -371,7 +371,7 @@ public:
&& (true && ... && CAssignableFrom<Ts&, Us&&>))
FORCEINLINE constexpr TTuple& operator=(TTuple<Us...>&& InValue)
{
Helper::Assign(*this, MoveTemp(InValue));
FHelper::Assign(*this, MoveTemp(InValue));
return *this;
}
@ -396,8 +396,8 @@ public:
template <typename... Us> requires (sizeof...(Ts) == sizeof...(Us) && NAMESPACE_PRIVATE::CTTupleSynthThreeWayComparable<TTypeSequence<Ts...>, TTypeSequence<Us...>>)
NODISCARD friend FORCEINLINE constexpr TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...> operator<=>(const TTuple& LHS, const TTuple<Us...>& RHS)
{
using R = TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...>;
return NAMESPACE_PRIVATE::TTupleThreeWay<R, TMakeIndexSequence<sizeof...(Ts)>>::Do(LHS, RHS);
using FResult = TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...>;
return NAMESPACE_PRIVATE::TTupleThreeWay<FResult, TMakeIndexSequence<sizeof...(Ts)>>::Do(LHS, RHS);
}
/** Extracts the Ith element from the tuple. I must be an integer value in [0, sizeof...(Ts)). */
@ -421,14 +421,14 @@ public:
template <typename T> NODISCARD FORCEINLINE constexpr decltype(auto) GetValue() const volatile&& { return static_cast<const volatile TTuple&&>(*this).GetValue<TTupleIndex<T, TTuple>>(); }
/** Invoke the callable object 'Func' with a tuple of arguments. */
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) & { return Helper::Apply(Forward<F>(Func), static_cast< TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const & { return Helper::Apply(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile& { return Helper::Apply(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile& { return Helper::Apply(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) && { return Helper::Apply(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const && { return Helper::Apply(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile&& { return Helper::Apply(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile&& { return Helper::Apply(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) & { return FHelper::Apply(Forward<F>(Func), static_cast< TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const & { return FHelper::Apply(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile& { return FHelper::Apply(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile& { return FHelper::Apply(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) && { return FHelper::Apply(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const && { return FHelper::Apply(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile&& { return FHelper::Apply(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile&& { return FHelper::Apply(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this)); }
/** Visits each element in a tuple in parallel and applies it as arguments to the function. */
template <typename F> requires (true && ... && CInvocable<F, Ts>) FORCEINLINE constexpr void Visit(F&& Func) & { VisitTuple(Forward<F>(Func), static_cast< TTuple& >(*this)); }
@ -461,24 +461,24 @@ public:
template <typename Ret, typename F> requires ((sizeof...(Ts) >= 1) && ... && CInvocableResult<Ret, F, Ts>) FORCEINLINE constexpr Ret Visit(F&& Func, size_t Index) const volatile&& { return NAMESPACE_PRIVATE::TTupleVisitElementByIndex<Ret, TMakeIndexSequence<sizeof...(Ts)>>::Do(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this), Index); }
/** Transform a tuple into another tuple using the given function. */
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) & { return Helper::Transform(Forward<F>(Func), static_cast< TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const & { return Helper::Transform(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile& { return Helper::Transform(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile& { return Helper::Transform(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) && { return Helper::Transform(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const && { return Helper::Transform(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile&& { return Helper::Transform(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile&& { return Helper::Transform(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) & { return FHelper::Transform(Forward<F>(Func), static_cast< TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const & { return FHelper::Transform(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile& { return FHelper::Transform(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile& { return FHelper::Transform(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) && { return FHelper::Transform(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const && { return FHelper::Transform(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile&& { return FHelper::Transform(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile&& { return FHelper::Transform(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this)); }
/** Constructs an object of type T with a tuple as an argument. */
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() & { return Helper::template Construct<T>(static_cast< TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const & { return Helper::template Construct<T>(static_cast<const TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile& { return Helper::template Construct<T>(static_cast< volatile TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const volatile& { return Helper::template Construct<T>(static_cast<const volatile TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() && { return Helper::template Construct<T>(static_cast< TTuple&&>(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const && { return Helper::template Construct<T>(static_cast<const TTuple&&>(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile&& { return Helper::template Construct<T>(static_cast< volatile TTuple&&>(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const volatile&& { return Helper::template Construct<T>(static_cast<const volatile TTuple&&>(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() & { return FHelper::template Construct<T>(static_cast< TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const & { return FHelper::template Construct<T>(static_cast<const TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile& { return FHelper::template Construct<T>(static_cast< volatile TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const volatile& { return FHelper::template Construct<T>(static_cast<const volatile TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() && { return FHelper::template Construct<T>(static_cast< TTuple&&>(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const && { return FHelper::template Construct<T>(static_cast<const TTuple&&>(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile&& { return FHelper::template Construct<T>(static_cast< volatile TTuple&&>(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const volatile&& { return FHelper::template Construct<T>(static_cast<const volatile TTuple&&>(*this)); }
/** @return The number of elements in the tuple. */
NODISCARD static FORCEINLINE constexpr size_t Num() { return sizeof...(Ts); }
@ -555,13 +555,13 @@ struct TTupleCatResultImpl;
template <typename... Ts, typename... TTupleTypes>
struct TTupleCatResultImpl<TTuple<Ts...>, TTupleTypes...>
{
using Type = typename TTupleCatResultImpl<TTupleTypes..., Ts...>::Type;
using FType = typename TTupleCatResultImpl<TTupleTypes..., Ts...>::FType;
};
template <typename... Ts>
struct TTupleCatResultImpl<FTupleEndFlag, Ts...>
{
using Type = TTuple<Ts...>;
using FType = TTuple<Ts...>;
};
template <typename R, typename Indices>
@ -571,14 +571,14 @@ template <typename... RTypes, size_t... Indices>
struct TTupleCatMake<TTuple<RTypes...>, TIndexSequence<Indices...>>
{
template <typename T, typename U>
struct ForwardType { using Type = TConditional<CRValueReference<T>, TRemoveReference<U>&&, U>; };
struct FForwardType { using FType = TConditional<CRValueReference<T>, TRemoveReference<U>&&, U>; };
template <typename TTupleType>
FORCEINLINE static constexpr TTuple<RTypes...> Do(TTupleType&& InValue)
{
return TTuple<RTypes...>
(
static_cast<typename ForwardType<RTypes, decltype(Forward<TTupleType>(InValue).template GetValue<Indices>())>::Type>
static_cast<typename FForwardType<RTypes, decltype(Forward<TTupleType>(InValue).template GetValue<Indices>())>::FType>
(
Forward<TTupleType>(InValue).template GetValue<Indices>()
)...
@ -642,15 +642,15 @@ struct TTupleVisitImpl<TIndexSequence<>>
NAMESPACE_PRIVATE_END
template <typename... TTupleTypes> requires (true && ... && CTTuple<TRemoveCVRef<TTupleTypes>>)
using TTupleCatResult = typename NAMESPACE_PRIVATE::TTupleCatResultImpl<TRemoveReference<TTupleTypes>..., NAMESPACE_PRIVATE::FTupleEndFlag>::Type;;
using TTupleCatResult = typename NAMESPACE_PRIVATE::TTupleCatResultImpl<TRemoveReference<TTupleTypes>..., NAMESPACE_PRIVATE::FTupleEndFlag>::FType;
/** Creates a tuple by concatenating any number of tuples. */
template <typename... TTupleTypes> requires (true && ... && CTTuple<TRemoveCVRef<TTupleTypes>>)
FORCEINLINE constexpr decltype(auto) TupleCat(TTupleTypes&&... Args)
{
using R = TTupleCatResult<TTupleTypes...>;
if constexpr (sizeof...(Args) == 0) return R();
else return NAMESPACE_PRIVATE::TTupleCatImpl<R>::Do(Forward<TTupleTypes>(Args)...);
using FResult = TTupleCatResult<TTupleTypes...>;
if constexpr (sizeof...(Args) == 0) return FResult();
else return NAMESPACE_PRIVATE::TTupleCatImpl<FResult>::Do(Forward<TTupleTypes>(Args)...);
}
/**
@ -679,20 +679,22 @@ FORCEINLINE constexpr void VisitTuple(F&& Func, FirstTupleType&& FirstTuple, Tup
template <typename... Ts, typename... Us> requires (requires { typename TTuple<TCommonType<Ts, Us>...>; })
struct TBasicCommonType<TTuple<Ts...>, TTuple<Us...>>
{
using Type = TTuple<TCommonType<Ts, Us>...>;
using FType = TTuple<TCommonType<Ts, Us>...>;
};
template <typename... Ts, typename... Us, template<typename> typename TQualifiers, template<typename> typename UQualifiers>
requires (requires { typename TTuple<TCommonReference<TQualifiers<Ts>, UQualifiers<Us>>...>; })
struct TBasicCommonReference<TTuple<Ts...>, TTuple<Us...>, TQualifiers, UQualifiers>
{
using Type = TTuple<TCommonReference<TQualifiers<Ts>, UQualifiers<Us>>...>;
using FType = TTuple<TCommonReference<TQualifiers<Ts>, UQualifiers<Us>>...>;
};
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END
// ReSharper disable CppInconsistentNaming
NAMESPACE_STD_BEGIN
// Support structure binding, should not be directly used.
@ -718,3 +720,5 @@ template <size_t Index, typename ...Ts> FORCEINLINE constexpr decltype(auto) get
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END
// ReSharper restore CppInconsistentNaming

View File

@ -24,8 +24,8 @@ void AsConst(const T&& Ref) = delete;
template <typename T>
FORCEINLINE constexpr TRemoveReference<T>&& MoveTemp(T&& Obj)
{
using CastType = TRemoveReference<T>;
return static_cast<CastType&&>(Obj);
using FCastType = TRemoveReference<T>;
return static_cast<FCastType&&>(Obj);
}
/** CopyTemp will enforce the creation of an rvalue which can bind to rvalue reference parameters. */

View File

@ -40,30 +40,30 @@ struct TVariantAlternativeImpl;
template <size_t I, typename... Ts>
struct TVariantAlternativeImpl<I, TVariant<Ts...>>
{
using Type = Meta::TType<I, TTypeSequence<Ts...>>;
using FType = Meta::TType<I, TTypeSequence<Ts...>>;
};
template <typename T, typename TSequence>
struct TVariantOverloadType
{
using FrontType = Meta::TFront<TSequence>;
using NextSequence = Meta::TPop<TSequence>;
using NextUniqueSequence = typename TVariantOverloadType<T, NextSequence>::Type;
using FFrontType = Meta::TFront<TSequence>;
using FNextSequence = Meta::TPop<TSequence>;
using FNextUniqueSequence = typename TVariantOverloadType<T, FNextSequence>::FType;
// T_i x[] = { Forward<T>(t) };
static constexpr bool bConditional = requires { DeclVal<void(FrontType(&&)[1])>()({ DeclVal<T>() }); };
static constexpr bool bConditional = requires { DeclVal<void(FFrontType(&&)[1])>()({ DeclVal<T>() }); };
using Type = TConditional<bConditional, Meta::TPush<FrontType, NextUniqueSequence>, NextUniqueSequence>;
using FType = TConditional<bConditional, Meta::TPush<FFrontType, FNextUniqueSequence>, FNextUniqueSequence>;
};
template <typename T>
struct TVariantOverloadType<T, TTypeSequence<>>
{
using Type = TTypeSequence<>;
using FType = TTypeSequence<>;
};
template <typename T, typename... Ts>
using TVariantSelectedType = Meta::TOverloadResolution<T, typename NAMESPACE_PRIVATE::TVariantOverloadType<T, TTypeSequence<Ts...>>::Type>;
using TVariantSelectedType = Meta::TOverloadResolution<T, typename NAMESPACE_PRIVATE::TVariantOverloadType<T, TTypeSequence<Ts...>>::FType>;
NAMESPACE_PRIVATE_END
@ -77,7 +77,7 @@ template <typename T, CTVariant U>
inline constexpr size_t TVariantIndex = NAMESPACE_PRIVATE::TVariantIndexImpl<T, TRemoveCV<U>>::Value;
template <size_t I, CTVariant U>
using TVariantAlternative = TCopyCV<U, typename NAMESPACE_PRIVATE::TVariantAlternativeImpl<I, TRemoveCV<U>>::Type>;
using TVariantAlternative = TCopyCV<U, typename NAMESPACE_PRIVATE::TVariantAlternativeImpl<I, TRemoveCV<U>>::FType>;
/**
* The class template TVariant represents a type-safe union. An instance of TVariant
@ -113,7 +113,7 @@ public:
{
if (IsValid()) MoveConstructImpl[InValue.GetIndex()](&Value, &InValue.Value);
}
/**
* Converting constructor. Constructs a variant holding the alternative type that would be selected
* by overload resolution for the expression F(Forward<T>(InValue)) if there was an overload of
@ -126,7 +126,7 @@ public:
&& !CSameAs<TVariant, TRemoveCVRef<T>>)
FORCEINLINE constexpr TVariant(T&& InValue) : TVariant(InPlaceType<NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>>, Forward<T>(InValue))
{ }
/** Constructs a variant with the specified alternative T and initializes the contained value with the arguments Forward<Us>(Args).... */
template <typename T, typename... Us> requires (CConstructibleFrom<T, Us...>)
FORCEINLINE constexpr explicit TVariant(TInPlaceType<T>, Us&&... Args)
@ -139,10 +139,10 @@ public:
FORCEINLINE constexpr explicit TVariant(TInPlaceIndex<I>, Us&&... Args)
: TypeIndex(I)
{
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
new (&Value) SelectedType(Forward<Us>(Args)...);
using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
new (&Value) FSelectedType(Forward<Us>(Args)...);
}
/** Constructs a variant with the specified alternative T and initializes the contained value with the arguments IL, Forward<Us>(Args).... */
template <typename T, typename U, typename... Us> requires (CConstructibleFrom<T, initializer_list<U>, Us...>)
FORCEINLINE constexpr explicit TVariant(TInPlaceType<T>, initializer_list<U> IL, Us&&... Args)
@ -155,8 +155,8 @@ public:
FORCEINLINE constexpr explicit TVariant(TInPlaceIndex<I>, initializer_list<T> IL, Us&&... Args)
: TypeIndex(I)
{
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
new (&Value) SelectedType(IL, Forward<Us>(Args)...);
using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
new (&Value) FSelectedType(IL, Forward<Us>(Args)...);
}
/** Destroys the contained object, if any, as if by a call to Reset(). */
@ -185,7 +185,7 @@ public:
if (GetIndex() == InValue.GetIndex()) CopyAssignImpl[InValue.GetIndex()](&Value, &InValue.Value);
else
{
{
Reset();
CopyConstructImpl[InValue.GetIndex()](&Value, &InValue.Value);
TypeIndex = static_cast<uint8>(InValue.GetIndex());
@ -224,14 +224,14 @@ public:
template <typename T> requires (requires { typename NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>; })
FORCEINLINE constexpr TVariant& operator=(T&& InValue)
{
using SelectedType = NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>;
using FSelectedType = NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>;
if (GetIndex() == TVariantIndex<SelectedType, TVariant<Ts...>>) GetValue<SelectedType>() = Forward<T>(InValue);
if (GetIndex() == TVariantIndex<FSelectedType, TVariant<Ts...>>) GetValue<FSelectedType>() = Forward<T>(InValue);
else
{
Reset();
new (&Value) SelectedType(Forward<T>(InValue));
TypeIndex = TVariantIndex<SelectedType, TVariant<Ts...>>;
new (&Value) FSelectedType(Forward<T>(InValue));
TypeIndex = TVariantIndex<FSelectedType, TVariant<Ts...>>;
}
return *this;
@ -277,7 +277,7 @@ public:
/** @return true if instance does not contain a value, otherwise false. */
NODISCARD FORCEINLINE constexpr bool operator==(FInvalid) const& { return !IsValid(); }
/** Equivalent to Emplace<I>(Forward<Us>(Args)...), where I is the zero-based index of T in Types.... */
template <typename T, typename... Us> requires (CConstructibleFrom<T, Us...>)
FORCEINLINE constexpr T& Emplace(Us&&... Args)
@ -290,7 +290,7 @@ public:
* Then direct-initializes the contained value as if constructing a value of type T with the arguments Forward<Us>(Args)....
*
* @param Args - The arguments to be passed to the constructor of the contained object.
*
*
* @return A reference to the new contained object.
*/
template <size_t I, typename... Us> requires (I < sizeof...(Ts)
@ -299,13 +299,13 @@ public:
{
Reset();
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
SelectedType* Result = new (&Value) SelectedType(Forward<Us>(Args)...);
using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
FSelectedType* Result = new (&Value) FSelectedType(Forward<Us>(Args)...);
TypeIndex = I;
return *Result;
}
/** Equivalent to Emplace<I>(IL, Forward<Us>(Args)...), where I is the zero-based index of T in Types.... */
template <typename T, typename U, typename... Us> requires (CConstructibleFrom<T, initializer_list<U>, Us...>)
FORCEINLINE constexpr T& Emplace(initializer_list<U> IL, Us&&... Args)
@ -318,7 +318,7 @@ public:
* Then direct-initializes the contained value as if constructing a value of type T with the arguments IL, Forward<Us>(Args)....
*
* @param IL, Args - The arguments to be passed to the constructor of the contained object.
*
*
* @return A reference to the new contained object.
*/
template <size_t I, typename T, typename... Us> requires (I < sizeof...(Ts)
@ -327,8 +327,8 @@ public:
{
Reset();
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
SelectedType* Result = new (&Value) SelectedType(IL, Forward<Us>(Args)...);
using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
FSelectedType* Result = new (&Value) FSelectedType(IL, Forward<Us>(Args)...);
TypeIndex = I;
return *Result;
@ -423,7 +423,7 @@ public:
}
private:
static constexpr const type_info* TypeInfos[] = { &typeid(Ts)... };
using FCopyConstructImpl = void(*)(void*, const void*);
@ -448,7 +448,7 @@ NAMESPACE_PRIVATE_BEGIN
template <typename F, typename... VariantTypes>
struct TVariantVisitImpl
{
struct GetTotalNum
struct FGetTotalNum
{
FORCEINLINE static constexpr size_t Do()
{
@ -464,10 +464,10 @@ struct TVariantVisitImpl
}
return Result;
};
}
};
struct EncodeIndices
struct FEncodeIndices
{
FORCEINLINE static constexpr size_t Do(initializer_list<size_t> Indices)
{
@ -482,10 +482,10 @@ struct TVariantVisitImpl
}
return Result;
};
}
};
struct DecodeExtent
struct FDecodeExtent
{
FORCEINLINE static constexpr size_t Do(size_t EncodedIndex, size_t Extent)
{
@ -497,76 +497,76 @@ struct TVariantVisitImpl
}
return EncodedIndex % VariantNums[Extent];
};
}
};
template <size_t EncodedIndex, typename>
struct InvokeEncoded;
struct FInvokeEncoded;
template <size_t EncodedIndex, size_t... ExtentIndices>
struct InvokeEncoded<EncodedIndex, TIndexSequence<ExtentIndices...>>
struct FInvokeEncoded<EncodedIndex, TIndexSequence<ExtentIndices...>>
{
FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants)
{
return Invoke(Forward<F>(Func), Forward<VariantTypes>(Variants).template GetValue<DecodeExtent::Do(EncodedIndex, ExtentIndices)>()...);
return Invoke(Forward<F>(Func), Forward<VariantTypes>(Variants).template GetValue<FDecodeExtent::Do(EncodedIndex, ExtentIndices)>()...);
}
template <typename Ret>
struct Result
struct FResult
{
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants)
{
return InvokeResult<Ret>(Forward<F>(Func), Forward<VariantTypes>(Variants).template GetValue<DecodeExtent::Do(EncodedIndex, ExtentIndices)>()...);
return InvokeResult<Ret>(Forward<F>(Func), Forward<VariantTypes>(Variants).template GetValue<FDecodeExtent::Do(EncodedIndex, ExtentIndices)>()...);
}
};
};
template <typename>
struct InvokeVariant;
struct FInvokeVariant;
template <size_t... EncodedIndices>
struct InvokeVariant<TIndexSequence<EncodedIndices...>>
struct FInvokeVariant<TIndexSequence<EncodedIndices...>>
{
FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants)
{
using ExtentIndices = TIndexSequenceFor<VariantTypes...>;
using FExtentIndices = TIndexSequenceFor<VariantTypes...>;
using ResultType = TCommonType<decltype(InvokeEncoded<EncodedIndices, ExtentIndices>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...))...>;
using InvokeImplType = ResultType(*)(F&&, VariantTypes&&...);
using FResultType = TCommonType<decltype(FInvokeEncoded<EncodedIndices, FExtentIndices>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...))...>;
constexpr InvokeImplType InvokeImpl[] = { InvokeEncoded<EncodedIndices, ExtentIndices>::template Result<ResultType>::Do... };
using FInvokeImplType = FResultType(*)(F&&, VariantTypes&&...);
return InvokeImpl[EncodeIndices::Do({ Variants.GetIndex()... })](Forward<F>(Func), Forward<VariantTypes>(Variants)...);
constexpr FInvokeImplType InvokeImpl[] = { FInvokeEncoded<EncodedIndices, FExtentIndices>::template FResult<FResultType>::Do... };
return InvokeImpl[FEncodeIndices::Do({ Variants.GetIndex()... })](Forward<F>(Func), Forward<VariantTypes>(Variants)...);
}
template <typename Ret>
struct Result
struct FResult
{
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants)
{
using ExtentIndices = TIndexSequenceFor<VariantTypes...>;
using FExtentIndices = TIndexSequenceFor<VariantTypes...>;
using InvokeImplType = Ret(*)(F&&, VariantTypes&&...);
using FInvokeImplType = Ret(*)(F&&, VariantTypes&&...);
constexpr InvokeImplType InvokeImpl[] = { InvokeEncoded<EncodedIndices, ExtentIndices>::template Result<Ret>::Do... };
constexpr FInvokeImplType InvokeImpl[] = { FInvokeEncoded<EncodedIndices, FExtentIndices>::template FResult<Ret>::Do... };
return InvokeImpl[EncodeIndices::Do({ Variants.GetIndex()... })](Forward<F>(Func), Forward<VariantTypes>(Variants)...);
return InvokeImpl[FEncodeIndices::Do({ Variants.GetIndex()... })](Forward<F>(Func), Forward<VariantTypes>(Variants)...);
}
};
};
FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants)
{
return InvokeVariant<TMakeIndexSequence<GetTotalNum::Do()>>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...);
return FInvokeVariant<TMakeIndexSequence<FGetTotalNum::Do()>>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...);
}
template <typename Ret>
struct Result
struct FResult
{
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants)
{
return InvokeVariant<TMakeIndexSequence<GetTotalNum::Do()>>::template Result<Ret>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...);
return FInvokeVariant<TMakeIndexSequence<FGetTotalNum::Do()>>::template FResult<Ret>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...);
}
};
};
@ -588,7 +588,7 @@ template <typename Ret, typename F, typename FirstVariantType, typename... Varia
constexpr Ret Visit(F&& Func, FirstVariantType&& FirstVariant, VariantTypes&&... Variants)
{
checkf((true && ... && Variants.IsValid()), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid()."));
return NAMESPACE_PRIVATE::TVariantVisitImpl<F, FirstVariantType, VariantTypes...>::template Result<Ret>::Do(Forward<F>(Func), Forward<FirstVariantType>(FirstVariant), Forward<VariantTypes>(Variants)...);
return NAMESPACE_PRIVATE::TVariantVisitImpl<F, FirstVariantType, VariantTypes...>::template FResult<Ret>::Do(Forward<F>(Func), Forward<FirstVariantType>(FirstVariant), Forward<VariantTypes>(Variants)...);
}
NAMESPACE_MODULE_END(Utility)

View File

@ -20,58 +20,58 @@ template <typename T, typename U, template <typename> typename TQualifiers, temp
NAMESPACE_PRIVATE_BEGIN
// Template class declaration for the common Type implementation
// Template class declaration for the common type implementation
template <typename...>
struct TCommonTypeImpl;
// If sizeof...(Ts) is zero, there is no member Type
// If sizeof...(Ts) is zero, there is no member FType
template <>
struct TCommonTypeImpl<> { };
// If sizeof...(Ts) is one, the member Type names the same Type as TCommonType<T, T> if it exists; otherwise there is no member Type
// If sizeof...(Ts) is one, the member FType names the same type as TCommonType<T, T> if it exists; otherwise there is no member FType
template <typename T>
struct TCommonTypeImpl<T> : TCommonTypeImpl<T, T> { };
// If sizeof...(Ts) is two
// If applying TDecay to at least one of T and U produces a different Type, the member Type names the same Type as TCommonType<TDecay<T>, TDecay<U>>, if it exists; if not, there is no member Type
// If applying TDecay to at least one of T and U produces a different type, the member FType names the same type as TCommonType<TDecay<T>, TDecay<U>>, if it exists; if not, there is no member FType
template <typename T, typename U> concept CDecayed = CSameAs<T, TDecay<T>> && CSameAs<U, TDecay<U>>;
template <typename T, typename U> requires (!CDecayed<T, U>)
struct TCommonTypeImpl<T, U> : TCommonTypeImpl<TDecay<T>, TDecay<U>> { };
// Otherwise, if there is a user specialization for TBasicCommonType<T, U>::Type, that specialization is used
template <typename T, typename U> concept CBasicCommonType = requires { typename TBasicCommonType<T, U>::Type; };
// Otherwise, if there is a user specialization for TBasicCommonType<T, U>::FType, that specialization is used
template <typename T, typename U> concept CBasicCommonType = requires { typename TBasicCommonType<T, U>::FType; };
template <typename T, typename U> requires (CDecayed<T, U> && CBasicCommonType<T, U>)
struct TCommonTypeImpl<T, U> : TBasicCommonType<T, U>
{
// If such a specialization has a member named type,
// it must be a public and unambiguous member that names a cv-unqualified non-reference type to which both T and U are explicitly convertible
// Additionally, TBasicCommonType<T, U>::Type and TBasicCommonType<U, T>::Type must denote the same type
static_assert(CSameAs<typename TBasicCommonType<T, U>::Type, TDecay<typename TBasicCommonType<T, U>::Type>>, "The basic common type must be a cv-unqualified non-reference type");
static_assert(CConstructibleFrom<typename TBasicCommonType<T, U>::Type, T&&> && CConstructibleFrom<typename TBasicCommonType<T, U>::Type, U&&>, "The basic common type must be a type which both T and U are explicitly convertible");
static_assert(CSameAs<typename TBasicCommonType<T, U>::Type, typename TBasicCommonType<U, T>::Type>, "TBasicCommonType<T, U>::Type and TBasicCommonType<U, T>::Type must denote the same type");
// Additionally, TBasicCommonType<T, U>::FType and TBasicCommonType<U, T>::FType must denote the same type
static_assert(CSameAs<typename TBasicCommonType<T, U>::FType, TDecay<typename TBasicCommonType<T, U>::FType>>, "The basic common type must be a cv-unqualified non-reference type");
static_assert(CConstructibleFrom<typename TBasicCommonType<T, U>::FType, T&&> && CConstructibleFrom<typename TBasicCommonType<T, U>::FType, U&&>, "The basic common type must be a type which both T and U are explicitly convertible");
static_assert(CSameAs<typename TBasicCommonType<T, U>::FType, typename TBasicCommonType<U, T>::FType>, "TBasicCommonType<T, U>::FType and TBasicCommonType<U, T>::FType must denote the same type");
};
// Otherwise, if TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())> is a valid Type, the member Type denotes that Type
// Otherwise, if TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())> is a valid type, the member FType denotes that type
template <typename T, typename U> concept CConditionalType = requires { typename TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())>; };
template <typename T, typename U> requires (CDecayed<T, U> && !CBasicCommonType<T, U> && CConditionalType<T, U>)
struct TCommonTypeImpl<T, U> { using Type = TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())>; };
struct TCommonTypeImpl<T, U> { using FType = TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())>; };
// Otherwise, if TDecay<decltype(false ? DeclVal<CRT>() : DeclVal<CRU>())> is a valid Type,
// where CRT and CRU are const TRemoveReference<T>& and const TRemoveReference<U>& respectively, the member Type denotes that Type
// Otherwise, if TDecay<decltype(false ? DeclVal<CRT>() : DeclVal<CRU>())> is a valid type,
// where CRT and CRU are const TRemoveReference<T>& and const TRemoveReference<U>& respectively, the member FType denotes that type
template <typename T, typename U> concept CConditionalCRefType = requires { typename TDecay<decltype(false ? DeclVal<const TRemoveReference<T>&>() : DeclVal<const TRemoveReference<U>&>())>; };
template <typename T, typename U> requires (CDecayed<T, U> && !CBasicCommonType<T, U> && !CConditionalType<T, U> && CConditionalCRefType<T, U>)
struct TCommonTypeImpl<T, U> { using Type = TDecay<decltype(false ? DeclVal<const TRemoveReference<T>&>() : DeclVal<const TRemoveReference<U>&>())>; };
struct TCommonTypeImpl<T, U> { using FType = TDecay<decltype(false ? DeclVal<const TRemoveReference<T>&>() : DeclVal<const TRemoveReference<U>&>())>; };
// Otherwise, there is no member Type
// Otherwise, there is no member FType
// If sizeof...(Ts) is greater than two
// If TCommonType<T, U> exists, the member Type denotes TCommonType<TCommonType<T, U>, R...> if such a Type exists
template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonTypeImpl<T, U>::Type; })
struct TCommonTypeImpl<T, U, W, Ts...> : TCommonTypeImpl<typename TCommonTypeImpl<T, U>::Type, W, Ts...> { };
// If TCommonType<T, U> exists, the member FType denotes TCommonType<TCommonType<T, U>, R...> if such a type exists
template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonTypeImpl<T, U>::FType; })
struct TCommonTypeImpl<T, U, W, Ts...> : TCommonTypeImpl<typename TCommonTypeImpl<T, U>::FType, W, Ts...> { };
// In all other cases, there is no member Type
// In all other cases, there is no member FType
template <typename...>
struct TCommonTypeImpl { };
@ -83,7 +83,7 @@ NAMESPACE_PRIVATE_BEGIN
template <typename...>
struct TCommonReferenceImpl;
// Template class declaration for the simple common reference Type implementation
// Template class declaration for the simple common reference type implementation
template <typename, typename>
struct TSimpleCommonReferenceImpl;
@ -91,89 +91,89 @@ struct TSimpleCommonReferenceImpl;
template <typename>
struct TQualifiersImpl;
// If sizeof...(T) is zero, there is no member Type
// If sizeof...(T) is zero, there is no member FType
template <>
struct TCommonReferenceImpl<> { };
// If sizeof...(T) is one, the member Type names the same Type as T
// If sizeof...(T) is one, the member FType names the same type as T
template <typename T>
struct TCommonReferenceImpl<T> { using Type = T; };
struct TCommonReferenceImpl<T> { using FType = T; };
// If sizeof...(Ts) is two
// If T and U are both reference types, and the simple common reference Type S of T and U exists, then the member Type Type names S
template <typename T, typename U> concept CSimpleCommonReference = requires { typename TSimpleCommonReferenceImpl<T, U>::Type; };
// If T and U are both reference types, and the simple common reference type S of T and U exists, then the member FType names S
template <typename T, typename U> concept CSimpleCommonReference = requires { typename TSimpleCommonReferenceImpl<T, U>::FType; };
template <typename T, typename U> requires (CSimpleCommonReference<T, U>)
struct TCommonReferenceImpl<T, U> : TSimpleCommonReferenceImpl<T, U> { };
// Otherwise, if TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQ, UQ>::Type exists
template <typename T, typename U> struct TBasicCommonReferenceImpl : TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQualifiersImpl<T>::template Apply, TQualifiersImpl<U>::template Apply> { };
template <typename T, typename U> concept CBasicCommonReference = requires { typename TBasicCommonReferenceImpl<T, U>::Type; };
// Otherwise, if TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQ, UQ>::FType exists
template <typename T, typename U> struct TBasicCommonReferenceImpl : TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQualifiersImpl<T>::template FApply, TQualifiersImpl<U>::template FApply> { };
template <typename T, typename U> concept CBasicCommonReference = requires { typename TBasicCommonReferenceImpl<T, U>::FType; };
template <typename T, typename U> requires (!CSimpleCommonReference<T, U> && CBasicCommonReference<T, U>)
struct TCommonReferenceImpl<T, U> : TBasicCommonReferenceImpl<T, U>
{
// If such a specialization has a member named type,
// it must be a public and unambiguous member that names a type to which both TQualifiers<T> and UQualifiers<U> are convertible
// Additionally, TBasicCommonReference<T, U, TQualifiers, UQualifiers>::Type and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::Type must denote the same type
static_assert(CConvertibleTo<T, typename TBasicCommonReferenceImpl<T, U>::Type> && CConvertibleTo<U, typename TBasicCommonReferenceImpl<T, U>::Type>, "The basic common reference must be a type to which both TQualifiers<T> and UQualifiers<U> are convertible");
static_assert(CSameAs<typename TBasicCommonReferenceImpl<T, U>::Type, typename TBasicCommonReferenceImpl<U, T>::Type>, "TBasicCommonReference<T, U, TQualifiers, UQualifiers>::Type and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::Type must denote the same type");
// Additionally, TBasicCommonReference<T, U, TQualifiers, UQualifiers>::FType and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::FType must denote the same type
static_assert(CConvertibleTo<T, typename TBasicCommonReferenceImpl<T, U>::FType> && CConvertibleTo<U, typename TBasicCommonReferenceImpl<T, U>::FType>, "The basic common reference must be a type to which both TQualifiers<T> and UQualifiers<U> are convertible");
static_assert(CSameAs<typename TBasicCommonReferenceImpl<T, U>::FType, typename TBasicCommonReferenceImpl<U, T>::FType>, "TBasicCommonReference<T, U, TQualifiers, UQualifiers>::FType and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::FType must denote the same type");
};
// Where TQ and UQ is a unary alias template such that TQ<U> is U with the addition of T's cv-ref qualifiers, then the member Type Type names that Type
template <typename T> struct TQualifiersImpl { template <typename U> using Apply = TCopyCV<T, U>; };
template <typename T> struct TQualifiersImpl<T&> { template <typename U> using Apply = TAddLValueReference<TCopyCV<T, U>>; };
template <typename T> struct TQualifiersImpl<T&&> { template <typename U> using Apply = TAddRValueReference<TCopyCV<T, U>>; };
// Where TQ and UQ is a unary alias template such that TQ<U> is U with the addition of T's cv-ref qualifiers, then the member FType names that type
template <typename T> struct TQualifiersImpl { template <typename U> using FApply = TCopyCV<T, U>; };
template <typename T> struct TQualifiersImpl<T&> { template <typename U> using FApply = TAddLValueReference<TCopyCV<T, U>>; };
template <typename T> struct TQualifiersImpl<T&&> { template <typename U> using FApply = TAddRValueReference<TCopyCV<T, U>>; };
// Otherwise, if decltype(false ? Val<T>() : Val<U>()), where val is a function template template <typename T> T Val();, is a valid Type, then the member Type Type names that Type
// Otherwise, if decltype(false ? Val<T>() : Val<U>()), where val is a function template <typename T> T Val();, is a valid type, then the member FType names that type
template <typename T> T Val();
template <typename T, typename U> concept CConditionalValType = requires { typename TVoid<decltype(false ? Val<T>() : Val<U>())>; };
template <typename T, typename U> requires (!CSimpleCommonReference<T, U> && !CBasicCommonReference<T, U> && CConditionalValType<T, U>)
struct TCommonReferenceImpl<T, U> { using Type = decltype(false ? Val<T>() : Val<U>()); };
struct TCommonReferenceImpl<T, U> { using FType = decltype(false ? Val<T>() : Val<U>()); };
// Otherwise, if TCommonType<T, U> is a valid Type, then the member Type Type names that Type
// Otherwise, if TCommonType<T, U> is a valid type, then the member FType names that type
template <typename T, typename U> concept CCommonTypeImpl = requires { typename TCommonTypeImpl<T, U>; };
template <typename T, typename U> requires (!CSimpleCommonReference<T, U> && !CBasicCommonReference<T, U> && !CConditionalValType<T, U> && CCommonTypeImpl<T, U>)
struct TCommonReferenceImpl<T, U> : TCommonTypeImpl<T, U> { };
// Otherwise, there is no member Type
// Otherwise, there is no member FType
// If sizeof...(Ts) is greater than two
// If TCommonReference<T, U> exists, the member Type denotes TCommonReference<TCommonReference<T, U>, R...> if such a Type exists
template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonReferenceImpl<T, U>::Type; })
struct TCommonReferenceImpl<T, U, W, Ts...> : TCommonReferenceImpl<typename TCommonReferenceImpl<T, U>::Type, W, Ts...> { };
// If TCommonReference<T, U> exists, the member FType denotes TCommonReference<TCommonReference<T, U>, R...> if such a type exists
template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonReferenceImpl<T, U>::FType; })
struct TCommonReferenceImpl<T, U, W, Ts...> : TCommonReferenceImpl<typename TCommonReferenceImpl<T, U>::FType, W, Ts...> { };
// In all other cases, there is no member Type
// In all other cases, there is no member FType
template <typename...>
struct TCommonReferenceImpl { };
// If T is CV1 X & and U is CV2 Y & (i.e., both are lvalue reference types):
// their simple common reference Type is decltype(false ? DeclVal<CV12 X &>() : DeclVal<CV12 Y &>()),
// where CV12 is the union of CV1 and CV2, if that Type exists and is a reference Type
// their simple common reference type is decltype(false ? DeclVal<CV12 X &>() : DeclVal<CV12 Y &>()),
// where CV12 is the union of CV1 and CV2, if that type exists and is a reference type
template <typename T, typename U> requires (CLValueReference<decltype(false ? DeclVal<TCopyCV<T, U>&>() : DeclVal<TCopyCV<U, T>&>())>)
struct TSimpleCommonReferenceImpl<T&, U&> { using Type = decltype(false ? DeclVal<TCopyCV<T, U>&>() : DeclVal<TCopyCV<U, T>&>()); };
struct TSimpleCommonReferenceImpl<T&, U&> { using FType = decltype(false ? DeclVal<TCopyCV<T, U>&>() : DeclVal<TCopyCV<U, T>&>()); };
// If T and U are both rvalue reference types:
// if the simple common reference Type of T & and U & exists, then let C denote that Type's corresponding rvalue reference Type
// If CConvertibleTo<T, C> and CConvertibleTo<U, C> are both true, then the simple common reference Type of T and U is C
template <typename T, typename U> requires (CConvertibleTo<T&&, TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::Type> &&> && CConvertibleTo<U&&, TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::Type> &&>)
struct TSimpleCommonReferenceImpl<T&&, U&&> { using Type = TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::Type> &&; };
// if the simple common reference type of T & and U & exists, then let C denote that type's corresponding rvalue reference type
// If CConvertibleTo<T, C> and CConvertibleTo<U, C> are both true, then the simple common reference type of T and U is C
template <typename T, typename U> requires (CConvertibleTo<T&&, TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::FType> &&> && CConvertibleTo<U&&, TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::FType> &&>)
struct TSimpleCommonReferenceImpl<T&&, U&&> { using FType = TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::FType> &&; };
// Otherwise, one of the two types must be an lvalue reference Type A & and the other must be an rvalue reference Type B &&
// Let D denote the simple common reference Type of A & and B const &, if any
// If D exists and CConvertibleTo<B&&, D> is true, then the simple common reference Type is D
template <typename T, typename U> requires (CConvertibleTo<U&&, typename TSimpleCommonReferenceImpl<T&, const U&>::Type>)
struct TSimpleCommonReferenceImpl<T&, U&&> { using Type = typename TSimpleCommonReferenceImpl<T&, const U&>::Type; };
// Otherwise, one of the two types must be a lvalue reference type A & and the other must be a rvalue reference type B &&
// Let D denote the simple common reference type of A & and B const &, if any
// If D exists and CConvertibleTo<B&&, D> is true, then the simple common reference type is D
template <typename T, typename U> requires (CConvertibleTo<U&&, typename TSimpleCommonReferenceImpl<T&, const U&>::FType>)
struct TSimpleCommonReferenceImpl<T&, U&&> { using FType = typename TSimpleCommonReferenceImpl<T&, const U&>::FType; };
template <typename T, typename U> struct TSimpleCommonReferenceImpl<T&&, U&> : TSimpleCommonReferenceImpl<U&, T&&> { }; // The order is not important
// Otherwise, there's no simple common reference Type
// Otherwise, there's no simple common reference type
template <typename T, typename U>
struct TSimpleCommonReferenceImpl { };
NAMESPACE_PRIVATE_END
template <typename... Ts> using TCommonType = typename NAMESPACE_PRIVATE::TCommonTypeImpl<Ts...>::Type;
template <typename... Ts> using TCommonReference = typename NAMESPACE_PRIVATE::TCommonReferenceImpl<Ts...>::Type;
template <typename... Ts> using TCommonType = typename NAMESPACE_PRIVATE::TCommonTypeImpl<Ts...>::FType;
template <typename... Ts> using TCommonReference = typename NAMESPACE_PRIVATE::TCommonReferenceImpl<Ts...>::FType;
template <typename... Ts>
concept CCommonReference =

View File

@ -11,35 +11,35 @@ NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_PRIVATE_BEGIN
template <typename From, typename To> struct TCopyConstImpl { using Type = To; };
template <typename From, typename To> struct TCopyConstImpl<const From, To> { using Type = const To; };
template <typename From, typename To> struct TCopyConstImpl { using FType = To; };
template <typename From, typename To> struct TCopyConstImpl<const From, To> { using FType = const To; };
template <typename From, typename To> struct TCopyVolatileImpl { using Type = To; };
template <typename From, typename To> struct TCopyVolatileImpl<volatile From, To> { using Type = volatile To; };
template <typename From, typename To> struct TCopyVolatileImpl { using FType = To; };
template <typename From, typename To> struct TCopyVolatileImpl<volatile From, To> { using FType = volatile To; };
template <typename From, typename To> struct TCopyCVImpl { using Type = typename TCopyConstImpl<From, typename TCopyVolatileImpl<From, To>::Type>::Type; };
template <typename From, typename To> struct TCopyCVImpl { using FType = typename TCopyConstImpl<From, typename TCopyVolatileImpl<From, To>::FType>::FType; };
template <typename From, typename To> struct TCopyReferenceImpl { using Type = To; };
template <typename From, typename To> struct TCopyReferenceImpl<From&, To> { using Type = To&; };
template <typename From, typename To> struct TCopyReferenceImpl<From&&, To> { using Type = To&&; };
template <typename From, typename To> struct TCopyReferenceImpl { using FType = To; };
template <typename From, typename To> struct TCopyReferenceImpl<From&, To> { using FType = To&; };
template <typename From, typename To> struct TCopyReferenceImpl<From&&, To> { using FType = To&&; };
template <typename From, typename To> struct TCopyCVRefImpl { using Type = typename TCopyCVImpl<From, To>::Type; };
template <typename From, typename To> struct TCopyCVRefImpl<From, To& > { using Type = typename TCopyCVImpl<From, To>::Type&; };
template <typename From, typename To> struct TCopyCVRefImpl<From, To&&> { using Type = typename TCopyCVImpl<From, To>::Type&&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&, To > { using Type = typename TCopyCVImpl<From, To>::Type&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&, To& > { using Type = typename TCopyCVImpl<From, To>::Type&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&, To&&> { using Type = typename TCopyCVImpl<From, To>::Type&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To > { using Type = typename TCopyCVImpl<From, To>::Type&&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To& > { using Type = typename TCopyCVImpl<From, To>::Type&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To&&> { using Type = typename TCopyCVImpl<From, To>::Type&&; };
template <typename From, typename To> struct TCopyCVRefImpl { using FType = typename TCopyCVImpl<From, To>::FType; };
template <typename From, typename To> struct TCopyCVRefImpl<From, To& > { using FType = typename TCopyCVImpl<From, To>::FType&; };
template <typename From, typename To> struct TCopyCVRefImpl<From, To&&> { using FType = typename TCopyCVImpl<From, To>::FType&&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&, To > { using FType = typename TCopyCVImpl<From, To>::FType&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&, To& > { using FType = typename TCopyCVImpl<From, To>::FType&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&, To&&> { using FType = typename TCopyCVImpl<From, To>::FType&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To > { using FType = typename TCopyCVImpl<From, To>::FType&&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To& > { using FType = typename TCopyCVImpl<From, To>::FType&; };
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To&&> { using FType = typename TCopyCVImpl<From, To>::FType&&; };
NAMESPACE_PRIVATE_END
template <typename From, typename To> using TCopyConst = typename NAMESPACE_PRIVATE::TCopyConstImpl<From, To>::Type;
template <typename From, typename To> using TCopyVolatile = typename NAMESPACE_PRIVATE::TCopyVolatileImpl<From, To>::Type;
template <typename From, typename To> using TCopyCV = typename NAMESPACE_PRIVATE::TCopyCVImpl<From, To>::Type;
template <typename From, typename To> using TCopyReference = typename NAMESPACE_PRIVATE::TCopyReferenceImpl<From, To>::Type;
template <typename From, typename To> using TCopyCVRef = typename NAMESPACE_PRIVATE::TCopyCVRefImpl<From, To>::Type;
template <typename From, typename To> using TCopyConst = typename NAMESPACE_PRIVATE::TCopyConstImpl <From, To>::FType;
template <typename From, typename To> using TCopyVolatile = typename NAMESPACE_PRIVATE::TCopyVolatileImpl <From, To>::FType;
template <typename From, typename To> using TCopyCV = typename NAMESPACE_PRIVATE::TCopyCVImpl <From, To>::FType;
template <typename From, typename To> using TCopyReference = typename NAMESPACE_PRIVATE::TCopyReferenceImpl<From, To>::FType;
template <typename From, typename To> using TCopyCVRef = typename NAMESPACE_PRIVATE::TCopyCVRefImpl <From, To>::FType;
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)

View File

@ -6,14 +6,14 @@ NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
template <typename InType, InType InValue>
template <typename T, T InValue>
struct TConstant
{
using ValueType = InType;
using Type = TConstant;
static constexpr ValueType Value = InValue;
FORCEINLINE constexpr operator ValueType() const { return Value; }
FORCEINLINE constexpr ValueType operator()() const { return Value; }
using FValueType = T;
using FType = TConstant;
static constexpr FValueType Value = InValue;
FORCEINLINE constexpr operator FValueType() const { return Value; }
FORCEINLINE constexpr FValueType operator()() const { return Value; }
};
template <bool InValue>