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 #endif
@ -80,7 +80,7 @@ void* Malloc(size_t Count, size_t Alignment)
check(Result != nullptr); check(Result != nullptr);
check_code({ MemoryLeakChecker.AddMemoryAllocationCount(); }); check_code({ GMemoryLeakChecker.AddMemoryAllocationCount(); });
return Result; return Result;
} }
@ -139,7 +139,7 @@ void Free(void* Ptr)
} }
# endif # endif
check_code({ MemoryLeakChecker.ReleaseMemoryAllocationCount(); }); check_code({ GMemoryLeakChecker.ReleaseMemoryAllocationCount(); });
} }
size_t QuantizeSize(size_t Count, size_t Alignment) size_t QuantizeSize(size_t Count, size_t Alignment)

View File

@ -10,15 +10,15 @@ NAMESPACE_BEGIN(Math)
NAMESPACE_UNNAMED_BEGIN NAMESPACE_UNNAMED_BEGIN
TAtomic<uint32> RandState = 586103306; TAtomic<uint32> GRandState = 586103306;
NAMESPACE_UNNAMED_END NAMESPACE_UNNAMED_END
uint32 Seed(uint32 InSeed) 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; return OldSeed;
} }
@ -27,7 +27,7 @@ uint32 Rand()
{ {
uint32 Result; uint32 Result;
RandState.FetchFn( GRandState.FetchFn(
[&Result](uint32 Value) [&Result](uint32 Value)
{ {
Result = Value; Result = Value;

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@ NAMESPACE_BEGIN(Testing)
NAMESPACE_UNNAMED_BEGIN NAMESPACE_UNNAMED_BEGIN
int32 TestObject; int32 GTestObject;
void TestFunction() { } void TestFunction() { }
struct FTestStructA { }; struct FTestStructA { };
@ -89,7 +89,7 @@ void TestTypeTraits()
always_check(!CLValueReference<int32>); always_check(!CLValueReference<int32>);
always_check(CLValueReference<int32&>); always_check(CLValueReference<int32&>);
always_check(!CLValueReference<int32&&>); always_check(!CLValueReference<int32&&>);
always_check(!CRValueReference<int32>); always_check(!CRValueReference<int32>);
always_check(!CRValueReference<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>>));
always_check((CSameAs<void, TVoid<int32, int64>>)); always_check((CSameAs<void, TVoid<int32, int64>>));
// Invocable.h // Invocable.h
always_check((CInvocable<int32()>)); always_check((CInvocable<int32()>));
always_check((CInvocable<int32(int32), int32>)); always_check((CInvocable<int32(int32), int32>));
always_check(!(CInvocable<int32(int32), FTestStructA>)); always_check(!(CInvocable<int32(int32), FTestStructA>));
@ -462,7 +462,7 @@ void TestTypeTraits()
always_check((CSameAs<int32, TCommonReference<int8, int32>>)); always_check((CSameAs<int32, TCommonReference<int8, int32>>));
always_check((CSameAs<int64, TCommonReference<int8, int32, int64>>)); always_check((CSameAs<int64, TCommonReference<int8, int32, int64>>));
always_check((CSameAs<double, TCommonReference<float, double>>)); always_check((CSameAs<double, TCommonReference<float, double>>));
always_check((CCommonType<int32, int32>)); always_check((CCommonType<int32, int32>));
always_check((CCommonType<int8, int32>)); always_check((CCommonType<int8, int32>));
always_check((CCommonType<float, double>)); 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< int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyConst<const 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<const volatile int32, TCopyConst<const volatile int32, const volatile int32>>));
always_check((CSameAs< int32, TCopyVolatile< int32, int32>>)); always_check((CSameAs< int32, TCopyVolatile< int32, int32>>));
always_check((CSameAs< int32, TCopyVolatile<const int32, int32>>)); always_check((CSameAs< int32, TCopyVolatile<const int32, int32>>));
always_check((CSameAs< volatile int32, TCopyVolatile<const volatile 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< int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyVolatile<const 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<const volatile int32, TCopyVolatile<const volatile int32, const volatile int32>>));
always_check((CSameAs< int32, TCopyCV< int32, int32>>)); always_check((CSameAs< int32, TCopyCV< int32, int32>>));
always_check((CSameAs<const int32, TCopyCV<const int32, int32>>)); always_check((CSameAs<const int32, TCopyCV<const int32, int32>>));
always_check((CSameAs<const volatile int32, TCopyCV<const volatile 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< int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyCV<const 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<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& >>)); 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< int32, const volatile int32>>));
always_check((CSameAs<const volatile int32, TCopyCVRef<const 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<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& >>)); 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: public:
using ElementType = T; using FElementType = T;
using AllocatorType = Allocator; using FAllocatorType = Allocator;
using Reference = T&; using FReference = T&;
using ConstReference = const T&; using FConstReference = const T&;
using Iterator = TIteratorImpl<false>; using FIterator = TIteratorImpl<false>;
using ConstIterator = TIteratorImpl<true >; using FConstIterator = TIteratorImpl<true >;
using ReverseIterator = TReverseIterator< Iterator>; using FReverseIterator = TReverseIterator< FIterator>;
using ConstReverseIterator = TReverseIterator<ConstIterator>; using FConstReverseIterator = TReverseIterator<FConstIterator>;
static_assert(CContiguousIterator< Iterator>); static_assert(CContiguousIterator< FIterator>);
static_assert(CContiguousIterator<ConstIterator>); static_assert(CContiguousIterator<FConstIterator>);
/** Default constructor. Constructs an empty container with a default-constructed allocator. */ /** Default constructor. Constructs an empty container with a default-constructed allocator. */
FORCEINLINE TArray() : TArray(0) { } FORCEINLINE TArray() : TArray(0) { }
/** Constructs the container with 'Count' default instances of T. */ /** 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.ArrayNum = Count;
Impl.ArrayMax = Impl->CalculateSlackReserve(Num()); Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
Impl.Pointer = Impl->Allocate(Max()); 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'. */ /** 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) : TArray(MakeCountedConstantIterator(InValue, Count), DefaultSentinel)
{ } { }
/** Constructs the container with the contents of the range ['First', 'Last'). */ /** 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) TArray(I First, S Last)
{ {
if constexpr (CForwardIterator<I>) if constexpr (CForwardIterator<I>)
@ -76,7 +76,7 @@ public:
for (size_t Index = 0; Index != Count; ++Index) for (size_t Index = 0; Index != Count; ++Index)
{ {
new (Impl.Pointer + Index) ElementType(*First++); new (Impl.Pointer + Index) FElementType(*First++);
} }
} }
else else
@ -94,17 +94,17 @@ public:
} }
/** Copy constructor. Constructs the container with the copy of the contents of 'InValue'. */ /** 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.ArrayNum = InValue.Num();
Impl.ArrayMax = Impl->CalculateSlackReserve(Num()); Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
Impl.Pointer = Impl->Allocate(Max()); 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. */ /** 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(); Impl.ArrayNum = InValue.Num();
@ -122,14 +122,14 @@ public:
Impl.ArrayMax = Impl->CalculateSlackReserve(Num()); Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
Impl.Pointer = Impl->Allocate(Max()); 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(); InValue.Reset();
} }
/** Constructs the container with the contents of the initializer list. */ /** 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. */ /** Destructs the array. The destructors of the elements are called and the used storage is deallocated. */
~TArray() ~TArray()
@ -139,7 +139,7 @@ public:
} }
/** Copy assignment operator. Replaces the contents with a copy of the contents of 'InValue'. */ /** 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; if (&InValue == this) UNLIKELY return *this;
@ -157,7 +157,7 @@ public:
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); 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; return *this;
} }
@ -170,7 +170,7 @@ public:
else if (InValue.Num() <= Max()) else if (InValue.Num() <= Max())
{ {
Memory::CopyAssign(Impl.Pointer, InValue.Impl.Pointer, Num()); 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(); else check_no_entry();
@ -180,7 +180,7 @@ public:
} }
/** Move assignment operator. After the move, 'InValue' is guaranteed to be empty. */ /** 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; if (&InValue == this) UNLIKELY return *this;
@ -214,7 +214,7 @@ public:
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); 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(); InValue.Reset();
@ -229,7 +229,7 @@ public:
else if (InValue.Num() <= Max()) else if (InValue.Num() <= Max())
{ {
Memory::MoveAssign(Impl.Pointer, InValue.Impl.Pointer, Num()); 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(); else check_no_entry();
@ -241,7 +241,7 @@ public:
} }
/** Replaces the contents with those identified by initializer list. */ /** 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); size_t NumToAllocate = GetNum(IL);
@ -257,7 +257,7 @@ public:
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); 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; return *this;
} }
@ -270,7 +270,7 @@ public:
else if (GetNum(IL) <= Max()) else if (GetNum(IL) <= Max())
{ {
Memory::CopyAssign(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), Num()); 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(); else check_no_entry();
@ -280,7 +280,7 @@ public:
} }
/** Compares the contents of two arrays. */ /** 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; if (LHS.Num() != RHS.Num()) return false;
@ -293,7 +293,7 @@ public:
} }
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */ /** 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(); const size_t NumToCompare = LHS.Num() < RHS.Num() ? LHS.Num() : RHS.Num();
@ -306,7 +306,7 @@ public:
} }
/** Inserts 'InValue' before 'Iter' in the container. */ /** 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().")); checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
@ -318,26 +318,26 @@ public:
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
ElementType* OldAllocation = Impl.Pointer; FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num(); const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() + 1; Impl.ArrayNum = Num() + 1;
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex); Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) ElementType(InValue); new (Impl.Pointer + InsertIndex) FElementType(InValue);
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex); Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
return Iterator(this, Impl.Pointer + InsertIndex); return FIterator(this, Impl.Pointer + InsertIndex);
} }
if (InsertIndex != Num()) 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) for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
{ {
@ -346,15 +346,15 @@ public:
Impl.Pointer[InsertIndex] = InValue; Impl.Pointer[InsertIndex] = InValue;
} }
else new (Impl.Pointer + Num()) ElementType(InValue); else new (Impl.Pointer + Num()) FElementType(InValue);
Impl.ArrayNum = Num() + 1; Impl.ArrayNum = Num() + 1;
return Iterator(this, Impl.Pointer + InsertIndex); return FIterator(this, Impl.Pointer + InsertIndex);
} }
/** Inserts 'InValue' before 'Iter' in the container. */ /** 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().")); checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
@ -366,26 +366,26 @@ public:
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
ElementType* OldAllocation = Impl.Pointer; FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num(); const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() + 1; Impl.ArrayNum = Num() + 1;
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex); Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) ElementType(MoveTemp(InValue)); new (Impl.Pointer + InsertIndex) FElementType(MoveTemp(InValue));
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex); Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
return Iterator(this, Impl.Pointer + InsertIndex); return FIterator(this, Impl.Pointer + InsertIndex);
} }
if (InsertIndex != Num()) 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) for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
{ {
@ -394,15 +394,15 @@ public:
Impl.Pointer[InsertIndex] = MoveTemp(InValue); 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; 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. */ /** 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().")); checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
@ -410,9 +410,9 @@ public:
} }
/** Inserts elements from range ['First', 'Last') before 'Iter'. */ /** Inserts elements from range ['First', 'Last') before 'Iter'. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>> template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>
&& CAssignableFrom<ElementType&, TIteratorReferenceType<I>> && CMovable<ElementType>) && CAssignableFrom<FElementType&, TIteratorReferenceType<I>> && CMovable<FElementType>)
Iterator Insert(ConstIterator Iter, I First, S Last) FIterator Insert(FConstIterator Iter, I First, S Last)
{ {
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator().")); checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
@ -423,7 +423,7 @@ public:
const size_t InsertIndex = Iter - Begin(); const size_t InsertIndex = Iter - Begin();
const size_t Count = Iteration::Distance(First, Last); 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(); const size_t NumToAllocate = Num() + Count > Max() ? Impl->CalculateSlackGrow(Num() + Count, Max()) : Max();
@ -431,26 +431,26 @@ public:
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
ElementType* OldAllocation = Impl.Pointer; FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num(); const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() + Count; Impl.ArrayNum = Num() + Count;
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); 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) 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); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); 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) 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) for (size_t TargetIndex = IndexD - 1; TargetIndex != IndexC - 1; --TargetIndex)
@ -507,14 +507,14 @@ public:
for (size_t TargetIndex = IndexB; TargetIndex != IndexC; ++TargetIndex) for (size_t TargetIndex = IndexB; TargetIndex != IndexC; ++TargetIndex)
{ {
new (Impl.Pointer + TargetIndex) ElementType(*First++); new (Impl.Pointer + TargetIndex) FElementType(*First++);
} }
check(First == Last); check(First == Last);
Impl.ArrayNum = Num() + Count; Impl.ArrayNum = Num() + Count;
return Iterator(this, Impl.Pointer + InsertIndex); return FIterator(this, Impl.Pointer + InsertIndex);
} }
else else
{ {
@ -524,14 +524,14 @@ public:
} }
/** Inserts elements from initializer list before 'Iter' in the container. */ /** 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)); return Insert(Iter, Iteration::Begin(IL), Iteration::End(IL));
} }
/** Inserts a new element into the container directly before 'Iter'. */ /** Inserts a new element into the container directly before 'Iter'. */
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...> && CMovable<ElementType>) template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...> && CMovable<FElementType>)
Iterator Emplace(ConstIterator Iter, Ts&&... Args) FIterator Emplace(FConstIterator Iter, Ts&&... Args)
{ {
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator().")); checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
@ -543,43 +543,43 @@ public:
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
ElementType* OldAllocation = Impl.Pointer; FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num(); const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() + 1; Impl.ArrayNum = Num() + 1;
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex); Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) ElementType(Forward<Ts>(Args)...); new (Impl.Pointer + InsertIndex) FElementType(Forward<Ts>(Args)...);
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex); Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
return Iterator(this, Impl.Pointer + InsertIndex); return FIterator(this, Impl.Pointer + InsertIndex);
} }
if (InsertIndex != Num()) 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) for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
{ {
Impl.Pointer[Index] = MoveTemp(Impl.Pointer[Index - 1]); 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; 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. */ /** 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().")); 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. */ /** 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().")); checkf(IsValidIterator(First) && IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
const size_t EraseIndex = First - Begin(); const size_t EraseIndex = First - Begin();
const size_t EraseCount = Last - First; 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(); const size_t NumToAllocate = bAllowShrinking ? Impl->CalculateSlackShrink(Num() - EraseCount, Max()) : Max();
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
ElementType* OldAllocation = Impl.Pointer; FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num(); const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() - EraseCount; Impl.ArrayNum = Num() - EraseCount;
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, EraseIndex); Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, EraseIndex);
Memory::MoveConstruct<ElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount); Memory::MoveConstruct<FElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
return Iterator(this, Impl.Pointer + EraseIndex); return FIterator(this, Impl.Pointer + EraseIndex);
} }
for (size_t Index = EraseIndex + EraseCount; Index != Num(); ++Index) for (size_t Index = EraseIndex + EraseCount; Index != Num(); ++Index)
@ -625,11 +625,11 @@ public:
Impl.ArrayNum = Num() - EraseCount; 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. */ /** 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().")); 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. */ /** 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().")); checkf(IsValidIterator(First) && IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
const size_t EraseIndex = First - Begin(); const size_t EraseIndex = First - Begin();
const size_t EraseCount = Last - First; 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(); const size_t NumToAllocate = bAllowShrinking ? Impl->CalculateSlackShrink(Num() - EraseCount, Max()) : Max();
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
ElementType* OldAllocation = Impl.Pointer; FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num(); const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() - EraseCount; Impl.ArrayNum = Num() - EraseCount;
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, EraseIndex); Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, EraseIndex);
Memory::MoveConstruct<ElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount); Memory::MoveConstruct<FElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
return Iterator(this, Impl.Pointer + EraseIndex); return FIterator(this, Impl.Pointer + EraseIndex);
} }
for (size_t Index = 0; Index != EraseCount; ++Index) for (size_t Index = 0; Index != EraseCount; ++Index)
@ -677,24 +677,24 @@ public:
Impl.ArrayNum = Num() - EraseCount; 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. */ /** 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); EmplaceBack(InValue);
} }
/** Appends the given element value to the end of the container. */ /** 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)); EmplaceBack(MoveTemp(InValue));
} }
/** Appends a new element to the end of the container. */ /** Appends a new element to the end of the container. */
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...> && CMovable<ElementType>) template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...> && CMovable<FElementType>)
ElementType& EmplaceBack(Ts&&... Args) FElementType& EmplaceBack(Ts&&... Args)
{ {
const size_t NumToAllocate = Num() + 1 > Max() ? Impl->CalculateSlackGrow(Num() + 1, Max()) : Max(); const size_t NumToAllocate = Num() + 1 > Max() ? Impl->CalculateSlackGrow(Num() + 1, Max()) : Max();
@ -702,15 +702,15 @@ public:
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
ElementType* OldAllocation = Impl.Pointer; FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num(); const size_t NumToDestruct = Num();
Impl.ArrayNum = Num() + 1; Impl.ArrayNum = Num() + 1;
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num() - 1); Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num() - 1);
new (Impl.Pointer + Num() - 1) ElementType(Forward<Ts>(Args)...); new (Impl.Pointer + Num() - 1) FElementType(Forward<Ts>(Args)...);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
@ -718,7 +718,7 @@ public:
return Impl.Pointer[Num() - 1]; 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; Impl.ArrayNum = Num() + 1;
@ -726,13 +726,13 @@ public:
} }
/** Removes the last element of the container. The array cannot be empty. */ /** 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); Erase(End() - 1, bAllowShrinking);
} }
/** Resizes the container to contain 'Count' elements. Additional default elements are appended. */ /** 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; size_t NumToAllocate = Count;
@ -741,8 +741,8 @@ public:
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
ElementType* OldAllocation = Impl.Pointer; FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num(); const size_t NumToDestruct = Num();
Impl.ArrayNum = Count; Impl.ArrayNum = Count;
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
@ -750,12 +750,12 @@ public:
if (NumToDestruct <= Num()) if (NumToDestruct <= Num())
{ {
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, NumToDestruct); Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, NumToDestruct);
Memory::DefaultConstruct<ElementType>(Impl.Pointer + NumToDestruct, Num() - NumToDestruct); Memory::DefaultConstruct<FElementType>(Impl.Pointer + NumToDestruct, Num() - NumToDestruct);
} }
else else
{ {
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num()); Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
} }
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
@ -770,7 +770,7 @@ public:
} }
else if (Count <= Max()) else if (Count <= Max())
{ {
Memory::DefaultConstruct<ElementType>(Impl.Pointer + Num(), Count - Num()); Memory::DefaultConstruct<FElementType>(Impl.Pointer + Num(), Count - Num());
} }
else check_no_entry(); else check_no_entry();
@ -778,7 +778,7 @@ public:
} }
/** Resizes the container to contain 'Count' elements. Additional copies of 'InValue' are appended. */ /** 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; size_t NumToAllocate = Count;
@ -787,8 +787,8 @@ public:
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
ElementType* OldAllocation = Impl.Pointer; FElementType* OldAllocation = Impl.Pointer;
const size_t NumToDestruct = Num(); const size_t NumToDestruct = Num();
Impl.ArrayNum = Count; Impl.ArrayNum = Count;
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
@ -796,16 +796,16 @@ public:
if (NumToDestruct <= Num()) 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) for (size_t Index = NumToDestruct; Index != Num(); ++Index)
{ {
new (Impl.Pointer + Index) ElementType(InValue); new (Impl.Pointer + Index) FElementType(InValue);
} }
} }
else else
{ {
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num()); Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
} }
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
@ -822,7 +822,7 @@ public:
{ {
for (size_t Index = Num(); Index != Count; ++Index) for (size_t Index = Num(); Index != Count; ++Index)
{ {
new (Impl.Pointer + Index) ElementType(InValue); new (Impl.Pointer + Index) FElementType(InValue);
} }
} }
else check_no_entry(); 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'. */ /** 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; if (Count <= Max()) return;
const size_t NumToAllocate = Impl->CalculateSlackReserve(Count); const size_t NumToAllocate = Impl->CalculateSlackReserve(Count);
ElementType* OldAllocation = Impl.Pointer; FElementType* OldAllocation = Impl.Pointer;
check(NumToAllocate > Max()); check(NumToAllocate > Max());
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num()); Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
Memory::Destruct(OldAllocation, Num()); Memory::Destruct(OldAllocation, Num());
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
@ -858,32 +858,32 @@ public:
if (NumToAllocate == Max()) return; if (NumToAllocate == Max()) return;
ElementType* OldAllocation = Impl.Pointer; FElementType* OldAllocation = Impl.Pointer;
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num()); Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
Memory::Destruct(OldAllocation, Num()); Memory::Destruct(OldAllocation, Num());
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
} }
/** @return The pointer to the underlying element storage. */ /** @return The pointer to the underlying element storage. */
NODISCARD FORCEINLINE ElementType* GetData() { return Impl.Pointer; } NODISCARD FORCEINLINE FElementType* GetData() { return Impl.Pointer; }
NODISCARD FORCEINLINE const ElementType* GetData() const { return Impl.Pointer; } NODISCARD FORCEINLINE const FElementType* GetData() const { return Impl.Pointer; }
/** @return The iterator to the first or end element. */ /** @return The iterator to the first or end element. */
NODISCARD FORCEINLINE Iterator Begin() { return Iterator(this, Impl.Pointer); } NODISCARD FORCEINLINE FIterator Begin() { return FIterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE ConstIterator Begin() const { return ConstIterator(this, Impl.Pointer); } NODISCARD FORCEINLINE FConstIterator Begin() const { return FConstIterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE Iterator End() { return Iterator(this, Impl.Pointer + Num()); } NODISCARD FORCEINLINE FIterator End() { return FIterator(this, Impl.Pointer + Num()); }
NODISCARD FORCEINLINE ConstIterator End() const { return ConstIterator(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. */ /** @return The reverse iterator to the first or end element. */
NODISCARD FORCEINLINE ReverseIterator RBegin() { return ReverseIterator(End()); } NODISCARD FORCEINLINE FReverseIterator RBegin() { return FReverseIterator(End()); }
NODISCARD FORCEINLINE ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); } NODISCARD FORCEINLINE FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
NODISCARD FORCEINLINE ReverseIterator REnd() { return ReverseIterator(Begin()); } NODISCARD FORCEINLINE FReverseIterator REnd() { return FReverseIterator(Begin()); }
NODISCARD FORCEINLINE ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); } NODISCARD FORCEINLINE FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
/** @return The number of elements in the container. */ /** @return The number of elements in the container. */
NODISCARD FORCEINLINE size_t Num() const { return Impl.ArrayNum; } NODISCARD FORCEINLINE size_t Num() const { return Impl.ArrayNum; }
@ -895,17 +895,17 @@ public:
NODISCARD FORCEINLINE bool IsEmpty() const { return Num() == 0; } NODISCARD FORCEINLINE bool IsEmpty() const { return Num() == 0; }
/** @return true if the iterator is valid, false otherwise. */ /** @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. */ /** @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 FElementType& 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 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. */ /** @return The reference to the first or last element. */
NODISCARD FORCEINLINE ElementType& Front() { return *Begin(); } NODISCARD FORCEINLINE FElementType& Front() { return *Begin(); }
NODISCARD FORCEINLINE const ElementType& Front() const { return *Begin(); } NODISCARD FORCEINLINE const FElementType& Front() const { return *Begin(); }
NODISCARD FORCEINLINE ElementType& Back() { return *(End() - 1); } NODISCARD FORCEINLINE FElementType& Back() { return *(End() - 1); }
NODISCARD FORCEINLINE const ElementType& Back() const { return *(End() - 1); } NODISCARD FORCEINLINE const FElementType& Back() const { return *(End() - 1); }
/** Erases all elements from the container. After this call, Num() returns zero. */ /** Erases all elements from the container. After this call, Num() returns zero. */
void Reset(bool bAllowShrinking = true) void Reset(bool bAllowShrinking = true)
@ -929,11 +929,11 @@ public:
} }
/** Overloads the GetTypeHash algorithm for TArray. */ /** 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; 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)); Result = HashCombine(Result, GetTypeHash(*Iter));
} }
@ -942,7 +942,7 @@ public:
} }
/** Overloads the Swap algorithm for TArray. */ /** 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 = const bool bIsTransferable =
A.Impl->IsTransferable(A.Impl.Pointer) && A.Impl->IsTransferable(A.Impl.Pointer) &&
@ -966,13 +966,13 @@ public:
private: private:
ALLOCATOR_WRAPPER_BEGIN(AllocatorType, ElementType, Impl) ALLOCATOR_WRAPPER_BEGIN(FAllocatorType, FElementType, Impl)
{ {
size_t ArrayNum; size_t ArrayNum;
size_t ArrayMax; size_t ArrayMax;
ElementType* Pointer; FElementType* Pointer;
} }
ALLOCATOR_WRAPPER_END(AllocatorType, ElementType, Impl) ALLOCATOR_WRAPPER_END(FAllocatorType, FElementType, Impl)
private: private:
@ -981,7 +981,7 @@ private:
{ {
public: public:
using ElementType = TRemoveCV<T>; using FElementType = TRemoveCV<T>;
FORCEINLINE TIteratorImpl() = default; FORCEINLINE TIteratorImpl() = default;

View File

@ -29,15 +29,15 @@ class TArrayView
{ {
public: 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; 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'). */ /** 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) FORCEINLINE constexpr explicit (Extent != DynamicExtent) TArrayView(I InFirst, size_t InCount)
{ {
checkf(Extent == DynamicExtent || Extent == InCount, TEXT("Illegal range count. Please check 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'). */ /** 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) FORCEINLINE constexpr explicit (Extent != DynamicExtent) TArrayView(I InFirst, S InLast)
{ {
checkf(Extent == DynamicExtent || Extent == InLast - InFirst, TEXT("Illegal range iterator. Please check InLast - InFirst.")); 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'. */ /** Constructs an array view that is a view over the array 'InArray'. */
template <size_t N> requires (Extent == DynamicExtent || N == Extent) template <size_t N> requires (Extent == DynamicExtent || N == Extent)
FORCEINLINE constexpr TArrayView(ElementType(&InArray)[N]) FORCEINLINE constexpr TArrayView(FElementType(&InArray)[N])
{ {
Impl.Pointer = InArray; Impl.Pointer = InArray;
@ -93,23 +93,23 @@ public:
} }
/** Constructs an array view that is a view over the array 'InArray'. */ /** 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()) { } FORCEINLINE constexpr TArrayView(TStaticArray<U, N>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
/** Constructs an array view that is a view over the array 'InArray'. */ /** 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()) { } 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'. */ /** 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()) { } FORCEINLINE constexpr TArrayView(TArray<U, Allocator>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
/** Constructs an array view that is a view over the array 'InArray'. */ /** 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()) { } FORCEINLINE constexpr TArrayView(const TArray<U, Allocator>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
/** Converting constructor from another array view 'InValue'. */ /** 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) 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().")); 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; FORCEINLINE constexpr TArrayView& operator=(const TArrayView&) noexcept = default;
/** Compares the contents of two array views. */ /** 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; if (LHS.Num() != RHS.Num()) return false;
@ -142,7 +142,7 @@ public:
} }
/** Compares the contents of two array views. */ /** 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(); 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. */ /** 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) 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.")); 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. */ /** 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.")); 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. */ /** 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) 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.")); 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. */ /** 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.")); 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'. */ /** 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) if constexpr (Count != DynamicExtent)
{ {
return TArrayView<ElementType, SubviewExtent>(Begin() + Offset, Count); return TArrayView<FElementType, SubviewExtent>(Begin() + Offset, Count);
} }
else 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) if (Count != DynamicExtent)
{ {
return TArrayView<ElementType, DynamicExtent>(Begin() + Offset, Count); return TArrayView<FElementType, DynamicExtent>(Begin() + Offset, Count);
} }
else 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. */ /** Obtains an array view to the object representation of the elements of the array view. */
NODISCARD FORCEINLINE constexpr auto AsBytes() 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()); 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. */ /** Obtains an array view to the object representation of the elements of the array view. */
NODISCARD FORCEINLINE constexpr auto AsBytes() const 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 TArrayView<const uint8, BytesExtent>(reinterpret_cast<const uint8*>(GetData()), NumBytes());
} }
/** @return The pointer to the underlying element storage. */ /** @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. */ /** @return The iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(this, Impl.Pointer); } NODISCARD FORCEINLINE constexpr FIterator Begin() const { return FIterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE constexpr Iterator End() const { return Iterator(this, Impl.Pointer + Num()); } NODISCARD FORCEINLINE constexpr FIterator End() const { return FIterator(this, Impl.Pointer + Num()); }
/** @return The reverse iterator to the first or end element. */ /** @return The reverse iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() const { return ReverseIterator(End()); } NODISCARD FORCEINLINE constexpr FReverseIterator RBegin() const { return FReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr ReverseIterator REnd() const { return ReverseIterator(Begin()); } NODISCARD FORCEINLINE constexpr FReverseIterator REnd() const { return FReverseIterator(Begin()); }
/** @return The number of elements in the container. */ /** @return The number of elements in the container. */
NODISCARD FORCEINLINE constexpr size_t Num() const { if constexpr (Extent == DynamicExtent) { return Impl.ArrayNum; } return Extent; } NODISCARD FORCEINLINE constexpr size_t Num() const { if constexpr (Extent == DynamicExtent) { return Impl.ArrayNum; } return Extent; }
/** @return The number of bytes in the container. */ /** @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. */ /** @return true if the container is empty, false otherwise. */
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; } NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; }
/** @return true if the iterator is valid, false otherwise. */ /** @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. */ /** @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. */ /** @return The reference to the first or last element. */
NODISCARD FORCEINLINE constexpr Reference Front() const { return *Begin(); } NODISCARD FORCEINLINE constexpr FReference Front() const { return *Begin(); }
NODISCARD FORCEINLINE constexpr Reference Back() const { return *(End() - 1); } NODISCARD FORCEINLINE constexpr FReference Back() const { return *(End() - 1); }
/** Overloads the GetTypeHash algorithm for TArrayView. */ /** 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; 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)); Result = HashCombine(Result, GetTypeHash(*Iter));
} }
@ -291,7 +291,7 @@ public:
private: private:
struct FImplWithoutNum { ElementType* Pointer; }; struct FImplWithoutNum { FElementType* Pointer; };
struct FImplWithNum : FImplWithoutNum { size_t ArrayNum; }; struct FImplWithNum : FImplWithoutNum { size_t ArrayNum; };
@ -299,42 +299,42 @@ private:
public: public:
class Iterator final class FIterator final
{ {
public: public:
using ElementType = TRemoveCV<T>; using FElementType = TRemoveCV<T>;
FORCEINLINE constexpr Iterator() = default; FORCEINLINE constexpr FIterator() = default;
FORCEINLINE constexpr Iterator(const Iterator&) = default; FORCEINLINE constexpr FIterator(const FIterator&) = default;
FORCEINLINE constexpr Iterator(Iterator&&) = default; FORCEINLINE constexpr FIterator(FIterator&&) = default;
FORCEINLINE constexpr Iterator& operator=(const Iterator&) = default; FORCEINLINE constexpr FIterator& operator=(const FIterator&) = default;
FORCEINLINE constexpr Iterator& operator=(Iterator&&) = 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(true ); return *Pointer; }
NODISCARD FORCEINLINE constexpr T* operator->() const { CheckThis(false); 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 FIterator& operator++() { ++Pointer; CheckThis(); return *this; }
FORCEINLINE constexpr Iterator& 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 FIterator operator++(int) { FIterator 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 Iterator& operator+=(ptrdiff Offset) { Pointer += Offset; CheckThis(); return *this; } FORCEINLINE constexpr FIterator& 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; }
NODISCARD friend FORCEINLINE constexpr Iterator operator+(Iterator Iter, ptrdiff Offset) { 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 Iterator operator+(ptrdiff Offset, Iterator Iter) { Iterator 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: private:
@ -345,11 +345,11 @@ public:
T* Pointer = nullptr; T* Pointer = nullptr;
# if DO_CHECK # if DO_CHECK
FORCEINLINE constexpr Iterator(const TArrayView* InContainer, T* InPointer) FORCEINLINE constexpr FIterator(const TArrayView* InContainer, T* InPointer)
: Owner(InContainer), Pointer(InPointer) : Owner(InContainer), Pointer(InPointer)
{ } { }
# else # else
FORCEINLINE constexpr Iterator(const TArrayView* InContainer, T* InPointer) FORCEINLINE constexpr FIterator(const TArrayView* InContainer, T* InPointer)
: Pointer(InPointer) : Pointer(InPointer)
{ } { }
# endif # endif

View File

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

View File

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

View File

@ -25,22 +25,22 @@ private:
public: public:
using ElementType = T; using FElementType = T;
using Reference = T&; using FReference = T&;
using ConstReference = const T&; using FConstReference = const T&;
using Iterator = TIteratorImpl<false>; using FIterator = TIteratorImpl<false>;
using ConstIterator = TIteratorImpl<true >; using FConstIterator = TIteratorImpl<true >;
using ReverseIterator = TReverseIterator< Iterator>; using FReverseIterator = TReverseIterator< FIterator>;
using ConstReverseIterator = TReverseIterator<ConstIterator>; using FConstReverseIterator = TReverseIterator<FConstIterator>;
static_assert(CContiguousIterator< Iterator>); static_assert(CContiguousIterator< FIterator>);
static_assert(CContiguousIterator<ConstIterator>); static_assert(CContiguousIterator<FConstIterator>);
/** Compares the contents of two arrays. */ /** 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; if (LHS.Num() != RHS.Num()) return false;
@ -53,7 +53,7 @@ public:
} }
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */ /** 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(); 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. */ /** @return The pointer to the underlying element storage. */
NODISCARD FORCEINLINE constexpr ElementType* GetData() { return _; } NODISCARD FORCEINLINE constexpr FElementType* GetData() { return _; }
NODISCARD FORCEINLINE constexpr const ElementType* GetData() const { return _; } NODISCARD FORCEINLINE constexpr const FElementType* GetData() const { return _; }
/** @return The iterator to the first or end element. */ /** @return The iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr Iterator Begin() { return Iterator(this, _); } NODISCARD FORCEINLINE constexpr FIterator Begin() { return FIterator(this, _); }
NODISCARD FORCEINLINE constexpr ConstIterator Begin() const { return ConstIterator(this, _); } NODISCARD FORCEINLINE constexpr FConstIterator Begin() const { return FConstIterator(this, _); }
NODISCARD FORCEINLINE constexpr Iterator End() { return Iterator(this, _ + Num()); } NODISCARD FORCEINLINE constexpr FIterator End() { return FIterator(this, _ + Num()); }
NODISCARD FORCEINLINE constexpr ConstIterator End() const { return ConstIterator(this, _ + Num()); } NODISCARD FORCEINLINE constexpr FConstIterator End() const { return FConstIterator(this, _ + Num()); }
/** @return The reverse iterator to the first or end element. */ /** @return The reverse iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() { return ReverseIterator(End()); } NODISCARD FORCEINLINE constexpr FReverseIterator RBegin() { return FReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); } NODISCARD FORCEINLINE constexpr FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr ReverseIterator REnd() { return ReverseIterator(Begin()); } NODISCARD FORCEINLINE constexpr FReverseIterator REnd() { return FReverseIterator(Begin()); }
NODISCARD FORCEINLINE constexpr ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); } NODISCARD FORCEINLINE constexpr FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
/** @return The number of elements in the container. */ /** @return The number of elements in the container. */
NODISCARD FORCEINLINE constexpr size_t Num() const { return N; } NODISCARD FORCEINLINE constexpr size_t Num() const { return N; }
@ -88,24 +88,24 @@ public:
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; } NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; }
/** @return true if the iterator is valid, false otherwise. */ /** @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. */ /** @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 FElementType& 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 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. */ /** @return The reference to the first or last element. */
NODISCARD FORCEINLINE constexpr ElementType& Front() { return *Begin(); } NODISCARD FORCEINLINE constexpr FElementType& Front() { return *Begin(); }
NODISCARD FORCEINLINE constexpr const ElementType& Front() const { return *Begin(); } NODISCARD FORCEINLINE constexpr const FElementType& Front() const { return *Begin(); }
NODISCARD FORCEINLINE constexpr ElementType& Back() { return *(End() - 1); } NODISCARD FORCEINLINE constexpr FElementType& Back() { return *(End() - 1); }
NODISCARD FORCEINLINE constexpr const ElementType& Back() const { return *(End() - 1); } NODISCARD FORCEINLINE constexpr const FElementType& Back() const { return *(End() - 1); }
/** Overloads the GetTypeHash algorithm for TStaticArray. */ /** 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; 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)); Result = HashCombine(Result, GetTypeHash(*Iter));
} }
@ -114,7 +114,7 @@ public:
} }
/** Overloads the Swap algorithm for TStaticArray. */ /** 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 ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT
@ -127,7 +127,7 @@ private:
{ {
public: public:
using ElementType = TRemoveCV<T>; using FElementType = TRemoveCV<T>;
FORCEINLINE constexpr TIteratorImpl() = default; FORCEINLINE constexpr TIteratorImpl() = default;
@ -224,6 +224,8 @@ NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END NAMESPACE_REDCRAFT_END
// ReSharper disable CppInconsistentNaming
NAMESPACE_STD_BEGIN NAMESPACE_STD_BEGIN
// Support structure binding, should not be directly used. // 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(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END NAMESPACE_REDCRAFT_END
// ReSharper restore CppInconsistentNaming

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -140,7 +140,7 @@ NODISCARD FORCEINLINE constexpr auto MakeBackInserter(C& Container)
/** Creates an iterator adapter inserted in the container. */ /** Creates an iterator adapter inserted in the container. */
template <typename C> 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)); }); 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: public:
using IteratorType = I; using FIteratorType = I;
using ElementType = TIteratorElement<I>; using FElementType = TIteratorElement<I>;
FORCEINLINE constexpr TMoveIterator() requires (CDefaultConstructible<I>) = default; FORCEINLINE constexpr TMoveIterator() requires (CDefaultConstructible<I>) = default;
@ -38,7 +38,7 @@ public:
FORCEINLINE constexpr TMoveIterator& operator=(TMoveIterator&&) = default; FORCEINLINE constexpr TMoveIterator& operator=(TMoveIterator&&) = default;
FORCEINLINE constexpr ~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&>) 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()) { } 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 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 const FIteratorType& GetBase() const& { return Current; }
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); } NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { return MoveTemp(Current); }
private: private:
IteratorType Current; FIteratorType Current;
}; };
@ -100,7 +100,7 @@ class TMoveSentinel
{ {
public: public:
using SentinelType = S; using FSentinelType = S;
FORCEINLINE constexpr TMoveSentinel() = default; FORCEINLINE constexpr TMoveSentinel() = default;
FORCEINLINE constexpr TMoveSentinel(const TMoveSentinel&) = default; FORCEINLINE constexpr TMoveSentinel(const TMoveSentinel&) = default;
@ -109,7 +109,7 @@ public:
FORCEINLINE constexpr TMoveSentinel& operator=(TMoveSentinel&&) = default; FORCEINLINE constexpr TMoveSentinel& operator=(TMoveSentinel&&) = default;
FORCEINLINE constexpr ~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&>) 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) { } 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>) 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 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 const FSentinelType& GetBase() const& { return Last; }
NODISCARD FORCEINLINE constexpr SentinelType GetBase() && { return MoveTemp(Last); } NODISCARD FORCEINLINE constexpr FSentinelType GetBase() && { return MoveTemp(Last); }
private: private:
SentinelType Last; FSentinelType Last;
}; };

View File

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

View File

@ -25,9 +25,9 @@ class TReverseIterator final
{ {
public: public:
using IteratorType = I; using FIteratorType = I;
using ElementType = TIteratorElement<I>; using FElementType = TIteratorElement<I>;
FORCEINLINE constexpr TReverseIterator() = default; FORCEINLINE constexpr TReverseIterator() = default;
FORCEINLINE constexpr TReverseIterator(const TReverseIterator&) = default; FORCEINLINE constexpr TReverseIterator(const TReverseIterator&) = default;
@ -36,7 +36,7 @@ public:
FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&&) = default; FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&&) = default;
FORCEINLINE constexpr ~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&>) 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()) { } 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>) 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 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]; } 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 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 const FIteratorType& GetBase() const& { return Current; }
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); } NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { return MoveTemp(Current); }
private: private:
IteratorType Current; FIteratorType Current;
}; };

View File

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

View File

@ -17,7 +17,7 @@ concept CAllocatableObject = CObject<T> && !CConst<T> && !CVolatile<T> && CDestr
template <typename A, typename T = int> template <typename A, typename T = int>
concept CAllocator = !CSameAs<A, FAllocatorInterface> && CAllocatableObject<T> 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.Allocate(Num) } -> CSameAs<T*>;
{ Allocator.Deallocate(InPtr) } -> CSameAs<void>; { Allocator.Deallocate(InPtr) } -> CSameAs<void>;
@ -47,15 +47,15 @@ struct FAllocatorInterface
static constexpr bool bSupportsMultipleAllocation = true; static constexpr bool bSupportsMultipleAllocation = true;
template <CAllocatableObject T> template <CAllocatableObject T>
class ForElementType /*: private FSingleton*/ class TForElementType /*: private FSingleton*/
{ {
public: public:
ForElementType() = default; TForElementType() = default;
ForElementType(const ForElementType&) = delete; TForElementType(const TForElementType&) = delete;
ForElementType(ForElementType&&) = delete; TForElementType(TForElementType&&) = delete;
ForElementType& operator=(const ForElementType&) = delete; TForElementType& operator=(const TForElementType&) = delete;
ForElementType& operator=(ForElementType&&) = delete; TForElementType& operator=(TForElementType&&) = delete;
/** Allocates uninitialized storage. If 'InNum' is zero, return nullptr. */ /** Allocates uninitialized storage. If 'InNum' is zero, return nullptr. */
NODISCARD FORCEINLINE T* Allocate(size_t InNum) = delete; 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. */ /** This is heap allocator that calls Memory::Malloc() directly for memory allocation. */
struct FHeapAllocator struct FHeapAllocator
@ -118,15 +118,15 @@ struct FHeapAllocator
static constexpr bool bSupportsMultipleAllocation = true; static constexpr bool bSupportsMultipleAllocation = true;
template <CAllocatableObject T> template <CAllocatableObject T>
class ForElementType /*: private FSingleton*/ class TForElementType /*: private FSingleton*/
{ {
public: public:
ForElementType() = default; TForElementType() = default;
ForElementType(const ForElementType&) = delete; TForElementType(const TForElementType&) = delete;
ForElementType(ForElementType&&) = delete; TForElementType(TForElementType&&) = delete;
ForElementType& operator=(const ForElementType&) = delete; TForElementType& operator=(const TForElementType&) = delete;
ForElementType& operator=(ForElementType&&) = delete; TForElementType& operator=(TForElementType&&) = delete;
NODISCARD FORCEINLINE T* Allocate(size_t InNum) NODISCARD FORCEINLINE T* Allocate(size_t InNum)
{ {
@ -197,15 +197,15 @@ struct TInlineAllocator
static constexpr bool bSupportsMultipleAllocation = false; static constexpr bool bSupportsMultipleAllocation = false;
template <CAllocatableObject T> template <CAllocatableObject T>
class ForElementType /*: private FSingleton*/ class TForElementType /*: private FSingleton*/
{ {
public: public:
ForElementType() = default; TForElementType() = default;
ForElementType(const ForElementType&) = delete; TForElementType(const TForElementType&) = delete;
ForElementType(ForElementType&&) = delete; TForElementType(TForElementType&&) = delete;
ForElementType& operator=(const ForElementType&) = delete; TForElementType& operator=(const TForElementType&) = delete;
ForElementType& operator=(ForElementType&&) = delete; TForElementType& operator=(TForElementType&&) = delete;
NODISCARD FORCEINLINE T* Allocate(size_t InNum) NODISCARD FORCEINLINE T* Allocate(size_t InNum)
{ {
@ -279,15 +279,15 @@ struct FNullAllocator
static constexpr bool bSupportsMultipleAllocation = true; static constexpr bool bSupportsMultipleAllocation = true;
template <CAllocatableObject T> template <CAllocatableObject T>
class ForElementType /*: private FSingleton*/ class TForElementType /*: private FSingleton*/
{ {
public: public:
ForElementType() = default; TForElementType() = default;
ForElementType(const ForElementType&) = delete; TForElementType(const TForElementType&) = delete;
ForElementType(ForElementType&&) = delete; TForElementType(TForElementType&&) = delete;
ForElementType& operator=(const ForElementType&) = delete; TForElementType& operator=(const TForElementType&) = delete;
ForElementType& operator=(ForElementType&&) = delete; TForElementType& operator=(TForElementType&&) = delete;
NODISCARD FORCEINLINE T* Allocate(size_t InNum) { check_no_entry(); return nullptr; } 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 NAMESPACE_PRIVATE_BEGIN
template <typename RT, typename ST> 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> template <bool bEnableInput, typename RT, typename ST, typename... Ts>
class FInOutPtr final : private FSingleton 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>) 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)...); }) && (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>) || (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) auto OutPtr(ST& InPtr, Ts&&... Args)
{ {
return NAMESPACE_PRIVATE::FInOutPtr<false, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, ST, Ts...>(InPtr, Forward<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)...); }) && (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>) || (CConstructibleFrom<ST, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, Ts...> && CMoveAssignable<ST>)
&& requires(ST& SPtr) { { SPtr.Release() } -> CConvertibleTo<NAMESPACE_PRIVATE::TRawPointer<RT, 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) auto InOutPtr(ST& InPtr, Ts&&... Args)
{ {
return NAMESPACE_PRIVATE::FInOutPtr<true, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, ST, Ts...>(InPtr, Forward<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; static constexpr bool bIsPointer = true;
using PointerType = T*; using FPointerType = T*;
using ElementType = T; using FElementType = T;
static FORCEINLINE constexpr ElementType* ToAddress(PointerType InPtr) static FORCEINLINE constexpr FElementType* ToAddress(FPointerType InPtr)
{ {
return InPtr; return InPtr;
} }
@ -34,29 +34,29 @@ struct TPointerTraits<T(*)[]>
{ {
static constexpr bool bIsPointer = true; static constexpr bool bIsPointer = true;
using PointerType = T(*)[]; using FPointerType = T(*)[];
using ElementType = T; using FElementType = T;
static FORCEINLINE constexpr ElementType* ToAddress(PointerType InPtr) static FORCEINLINE constexpr FElementType* ToAddress(FPointerType InPtr)
{ {
return InPtr; return InPtr;
} }
}; };
/** A specialization of TPointerTraits is provided for pointer-like type. */ /** A specialization of TPointerTraits is provided for pointer-like type. */
#define DEFINE_TPointerTraits(TPtr) \ #define DEFINE_TPointerTraits(TPtr) \
template <typename T> \ template <typename T> \
struct TPointerTraits<TPtr<T>> \ struct TPointerTraits<TPtr<T>> \
{ \ { \
static constexpr bool bIsPointer = true; \ static constexpr bool bIsPointer = true; \
\ \
using PointerType = TPtr<T>; \ using FPointerType = TPtr<T>; \
using ElementType = TPtr<T>::ElementType; \ using FElementType = TPtr<T>::FElementType; \
\ \
static FORCEINLINE constexpr ElementType* ToAddress(const PointerType& InPtr) \ static FORCEINLINE constexpr FElementType* ToAddress(const FPointerType& InPtr) \
{ \ { \
return InPtr.Get(); \ return InPtr.Get(); \
} \ } \
}; };
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)

View File

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

View File

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

View File

@ -42,6 +42,8 @@ NAMESPACE_PRIVATE_END
# define DO_CHECK 0 # define DO_CHECK 0
#endif #endif
// ReSharper disable CppInconsistentNaming
#define always_check(InExpr) RS_CHECK_IMPL(InExpr) #define always_check(InExpr) RS_CHECK_IMPL(InExpr)
#define always_checkf(InExpr, InFormat, ...) RS_CHECK_F_IMPL(InExpr, InFormat, ##__VA_ARGS__) #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.") #define always_check_no_entry() always_checkf(false, "Enclosing block should never be called.")
@ -77,6 +79,8 @@ NAMESPACE_PRIVATE_END
#endif #endif
// ReSharper restore CppInconsistentNaming
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END 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 // 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; // ReSharper disable CppInconsistentNaming
typedef NAMESPACE_STD::weak_ordering weak_ordering;
typedef NAMESPACE_STD::strong_ordering strong_ordering; 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 NAMESPACE_PRIVATE_BEGIN
template<int32> struct TCommonComparisonCategoryBasic { }; template<int32> struct TCommonComparisonCategoryBasic { };
template<> struct TCommonComparisonCategoryBasic<0> { using Type = strong_ordering; }; template<> struct TCommonComparisonCategoryBasic<0> { using FType = strong_ordering; };
template<> struct TCommonComparisonCategoryBasic<2> { using Type = partial_ordering; }; template<> struct TCommonComparisonCategoryBasic<2> { using FType = partial_ordering; };
template<> struct TCommonComparisonCategoryBasic<4> { using Type = weak_ordering; }; template<> struct TCommonComparisonCategoryBasic<4> { using FType = weak_ordering; };
template<> struct TCommonComparisonCategoryBasic<6> { using Type = partial_ordering; }; template<> struct TCommonComparisonCategoryBasic<6> { using FType = partial_ordering; };
template <typename... Ts> template <typename... Ts>
struct TCommonComparisonCategoryImpl struct TCommonComparisonCategoryImpl
@ -32,13 +36,13 @@ struct TCommonComparisonCategoryImpl
CSameAs<Ts, weak_ordering > ? 4u : CSameAs<Ts, weak_ordering > ? 4u :
CSameAs<Ts, partial_ordering> ? 2u : 1u CSameAs<Ts, partial_ordering> ? 2u : 1u
) )
)> )>
{ }; { };
NAMESPACE_PRIVATE_END NAMESPACE_PRIVATE_END
template <typename... Ts> template <typename... Ts>
using TCommonComparisonCategory = typename NAMESPACE_PRIVATE::TCommonComparisonCategoryImpl<Ts...>::Type; using TCommonComparisonCategory = typename NAMESPACE_PRIVATE::TCommonComparisonCategoryImpl<Ts...>::FType;
template <typename T, typename OrderingType> template <typename T, typename OrderingType>
concept CThreeWayComparesAs = CSameAs<TCommonComparisonCategory<T, OrderingType>, OrderingType>; concept CThreeWayComparesAs = CSameAs<TCommonComparisonCategory<T, OrderingType>, OrderingType>;

View File

@ -17,7 +17,7 @@ class TConstantIterator final
{ {
public: public:
using ElementType = TRemoveCV<T>; using FElementType = TRemoveCV<T>;
FORCEINLINE constexpr TConstantIterator() = default; FORCEINLINE constexpr TConstantIterator() = default;
@ -70,7 +70,7 @@ class TConstantIterator<T&> final
{ {
public: public:
using ElementType = TRemoveCV<T>; using FElementType = TRemoveCV<T>;
FORCEINLINE constexpr TConstantIterator() = default; FORCEINLINE constexpr TConstantIterator() = default;
@ -115,14 +115,14 @@ class TCountedIterator<TConstantIterator<T>> final
{ {
public: public:
using IteratorType = TConstantIterator<T>; using FIteratorType = TConstantIterator<T>;
using ElementType = typename TConstantIterator<T>::ElementType; using FElementType = typename TConstantIterator<T>::FElementType;
# if DO_CHECK # if DO_CHECK
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<IteratorType>) : Length(1), MaxLength(0) { } FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<FIteratorType>) : Length(1), MaxLength(0) { }
# else # else
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<IteratorType>) = default; FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<FIteratorType>) = default;
# endif # endif
FORCEINLINE constexpr TCountedIterator(const TCountedIterator&) = default; FORCEINLINE constexpr TCountedIterator(const TCountedIterator&) = default;
@ -132,25 +132,25 @@ public:
FORCEINLINE constexpr ~TCountedIterator() = default; 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; }); } 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&>) template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConstructibleFrom<FIteratorType, 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; }); } 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>) template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConstructibleFrom<FIteratorType, J>)
FORCEINLINE constexpr explicit (!CConvertibleTo<J&&, IteratorType>) TCountedIterator(TCountedIterator<J>&& InValue) : Current(MoveTemp(InValue).Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); } 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; } 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; } 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; } 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 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); } 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; } 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, 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-(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 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 const FIteratorType& GetBase() const& { CheckThis(); return Current; }
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { CheckThis(); return MoveTemp(Current); } NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { CheckThis(); return MoveTemp(Current); }
NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; } NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; }
private: private:
IteratorType Current; FIteratorType Current;
ptrdiff Length; ptrdiff Length;
# if DO_CHECK # if DO_CHECK
ptrdiff MaxLength; ptrdiff MaxLength;

View File

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

View File

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

View File

@ -444,83 +444,83 @@ RESOLVE_ARITHMETIC_AMBIGUITY_2_ARGS(CArithmetic, IsNearlyZero)
template <CFloatingPoint T> template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr bool IsInfinity(T A) 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. */ /** @return true if the given value is NaN, false otherwise. */
template <CFloatingPoint T> template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr bool IsNaN(T A) 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. */ /** @return true if the given value is normal, false otherwise. */
template <CFloatingPoint T> template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr bool IsNormal(T A) 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. */ /** @return true if the given value is subnormal, false otherwise. */
template <CFloatingPoint T> template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr bool IsDenorm(T A) 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. */ /** @return true if the given value is negative, even -0.0, false otherwise. */
template <CFloatingPoint T> template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr bool IsNegative(T A) 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. */ /** @return The exponent of the given value. */
template <CFloatingPoint T> template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr uint Exponent(T A) 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. */ /** @return The NaN value with the given payload. */
template <CFloatingPoint T, CUnsignedIntegral U> template <CFloatingPoint T, CUnsignedIntegral U>
NODISCARD FORCEINLINE constexpr T NaN(U Payload) 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 != 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(); 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. */ /** @return The NaN value with the given payload. */
@ -536,11 +536,11 @@ NODISCARD FORCEINLINE constexpr T NaN(U Payload)
template <CFloatingPoint T> template <CFloatingPoint T>
NODISCARD FORCEINLINE constexpr auto NaNPayload(T A) 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. */ /** @return The NaN payload of the given value. */

View File

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

View File

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

View File

@ -2,6 +2,7 @@
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/View.h" #include "Range/View.h"
#include "Range/Pipe.h"
#include "Range/Utility.h" #include "Range/Utility.h"
#include "Range/AllView.h" #include "Range/AllView.h"
#include "Memory/Address.h" #include "Memory/Address.h"
@ -30,20 +31,20 @@ private:
public: public:
using ElementType = TRangeElement<V>; using FElementType = TRangeElement<V>;
using Reference = TRangeReference<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 TFilterView() requires (CDefaultConstructible<V> && CDefaultConstructible<Pred>) = default;
FORCEINLINE constexpr explicit TFilterView(V InBase, Pred InPredicate) : Base(MoveTemp(InBase)), Predicate(MoveTemp(InPredicate)) { } 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 do
{ {
@ -60,7 +61,7 @@ public:
return Iter; 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() const& requires (CCopyConstructible<V>) { return Base; }
NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); } NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); }
@ -78,7 +79,7 @@ private:
public: 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. 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> template <typename Pred>
NODISCARD FORCEINLINE constexpr auto Filter(Pred&& Predicate) 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) 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/Utility.h"
#include "Range/View.h" #include "Range/View.h"
#include "Range/Factory.h" #include "Range/Factory.h"
#include "Range/Pipe.h"
#include "Range/AllView.h" #include "Range/AllView.h"
#include "Range/FilterView.h" #include "Range/FilterView.h"
#include "Range/TransformView.h" #include "Range/TransformView.h"

View File

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

View File

@ -11,7 +11,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_BEGIN(Range) 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>>) template <CClass T> requires (CSameAs<T, TRemoveCV<T>>)
class IBasicViewInterface class IBasicViewInterface
{ {
@ -100,7 +100,7 @@ class TRangeView : public IBasicViewInterface<TRangeView<I, S>>
{ {
public: public:
using ElementType = TIteratorElementType<I>; using FElementType = TIteratorElementType<I>;
FORCEINLINE constexpr TRangeView() requires (CDefaultConstructible<I>) = default; 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> template <CCharType T>
struct TChar struct TChar
{ {
using CharType = T; using FCharType = T;
/** The maximum number of code units required to represent a single character. if unknown, guess 1. */ /** The maximum number of code units required to represent a single character. if unknown, guess 1. */
static constexpr size_t MaxCodeUnitLength = static constexpr size_t MaxCodeUnitLength =
CSameAs<CharType, char> ? MB_LEN_MAX : CSameAs<FCharType, char> ? MB_LEN_MAX :
CSameAs<CharType, wchar> ? CSameAs<FCharType, wchar> ?
PLATFORM_WINDOWS ? 2 : PLATFORM_WINDOWS ? 2 :
PLATFORM_LINUX ? 1 : 1 : PLATFORM_LINUX ? 1 : 1 :
CSameAs<CharType, u8char> ? 4 : CSameAs<FCharType, u8char> ? 4 :
CSameAs<CharType, u16char> ? 2 : CSameAs<FCharType, u16char> ? 2 :
CSameAs<CharType, u32char> ? 1 : 1; CSameAs<FCharType, u32char> ? 1 : 1;
/** Whether the character type is fixed-length. */ /** Whether the character type is fixed-length. */
static constexpr bool bIsFixedLength = MaxCodeUnitLength == 1; 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; if ((InChar & 0b10000000) == 0b00000000) return true;
return false; 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 >= 0xD800 && InChar <= 0xDBFF) return false;
if (InChar >= 0xDC00 && InChar <= 0xDFFF) return false; if (InChar >= 0xDC00 && InChar <= 0xDFFF) return false;
@ -101,30 +101,30 @@ struct TChar
} }
// Windows uses UTF-16 encoding for wchar. // 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)); return TChar::IsValid(static_cast<u16char>(InChar));
} }
// Linux uses UTF-32 encoding for wchar. // 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)); 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; 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; return false;
} }
else if constexpr (CSameAs<CharType, u16char>) else if constexpr (CSameAs<FCharType, u16char>)
{ {
if (InChar >= U16TEXT('\uFDD0') && InChar <= U16TEXT('\uFDEF')) return true; if (InChar >= U16TEXT('\uFDD0') && InChar <= U16TEXT('\uFDEF')) return true;
@ -134,7 +134,7 @@ struct TChar
return false; return false;
} }
else if constexpr (CSameAs<CharType, u32char>) else if constexpr (CSameAs<FCharType, u32char>)
{ {
if (InChar >= U32TEXT('\uFDD0') && InChar <= U32TEXT('\uFDEF')) return true; if (InChar >= U32TEXT('\uFDD0') && InChar <= U32TEXT('\uFDEF')) return true;
@ -144,25 +144,25 @@ struct TChar
} }
// Windows uses UTF-16 encoding for wchar. // 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)); return TChar::IsNonch(static_cast<u16char>(InChar));
} }
// Linux uses UTF-32 encoding for wchar. // 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)); 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; 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 constexpr bool ASCIICompatible = []() -> bool
{ {
@ -188,7 +188,7 @@ struct TChar
return ASCIICompatible && 0x00 <= InChar && InChar <= 0x7F; return ASCIICompatible && 0x00 <= InChar && InChar <= 0x7F;
} }
else if constexpr (CSameAs<CharType, wchar>) else if constexpr (CSameAs<FCharType, wchar>)
{ {
constexpr bool ASCIICompatible = []() -> bool constexpr bool ASCIICompatible = []() -> bool
{ {
@ -214,19 +214,19 @@ struct TChar
return ASCIICompatible && 0x00 <= InChar && InChar <= 0x7F; 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; return InChar <= 0x7F;
} }
else static_assert(sizeof(CharType) == -1, "Unsupported character type"); else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false; 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(""); NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isalnum(InChar, 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(""); NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isalpha(InChar, Loc); return NAMESPACE_STD::isalpha(InChar, Loc);
} }
else if constexpr (CSameAs<CharType, u8char>) else if constexpr (CSameAs<FCharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -258,29 +258,29 @@ struct TChar
return false; 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)); 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; 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(""); NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::islower(InChar, Loc); return NAMESPACE_STD::islower(InChar, Loc);
} }
else if constexpr (CSameAs<CharType, u8char>) else if constexpr (CSameAs<FCharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -291,7 +291,7 @@ struct TChar
return false; 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.")); 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)); 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.")); 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)); 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; 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(""); NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isupper(InChar, Loc); return NAMESPACE_STD::isupper(InChar, Loc);
} }
else if constexpr (CSameAs<CharType, u8char>) else if constexpr (CSameAs<FCharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -333,7 +333,7 @@ struct TChar
return false; 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.")); 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)); 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.")); 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)); 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; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsDigit(CharType InChar) NODISCARD FORCEINLINE static constexpr bool IsDigit(FCharType InChar)
{ {
static_assert(TChar::IsASCII()); static_assert(TChar::IsASCII());
/* <U0030>..<U0039>; */ /* <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].")); checkf(Base >= 2 && Base <= 36, TEXT("Base must be in the range [2, 36]."));
@ -373,32 +373,32 @@ struct TChar
bool bResult = false; bool bResult = false;
/* <U0030>..<U0039>; */ /* <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>; */ /* <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>; */ /* <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; 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(""); NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::iscntrl(InChar, Loc); return NAMESPACE_STD::iscntrl(InChar, Loc);
} }
else if constexpr (CSameAs<CharType, u8char>) else if constexpr (CSameAs<FCharType, u8char>)
{ {
/* <U0000>..<U001F>;<U007F>; */ /* <U0000>..<U001F>;<U007F>; */
return (InChar >= U8TEXT('\u0000') && InChar <= U8TEXT('\u001F')) || InChar == U8TEXT('\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>; */ /* <U0000>..<U001F>;<U007F>..<U009F>;<U2028>;<U2029>; */
return return
@ -407,7 +407,7 @@ struct TChar
(InChar == U16TEXT('\u2028') || InChar == U16TEXT('\u2029')); (InChar == U16TEXT('\u2028') || InChar == U16TEXT('\u2029'));
} }
else if constexpr (CSameAs<CharType, u32char>) else if constexpr (CSameAs<FCharType, u32char>)
{ {
/* <U0000>..<U001F>;<U007F>..<U009F>;<U2028>;<U2029>; */ /* <U0000>..<U001F>;<U007F>..<U009F>;<U2028>;<U2029>; */
return return
@ -416,20 +416,20 @@ struct TChar
(InChar == U32TEXT('\u2028') || InChar == U32TEXT('\u2029')); (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; 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(""); NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isgraph(InChar, Loc); return NAMESPACE_STD::isgraph(InChar, Loc);
} }
else if constexpr (CSameAs<CharType, u8char>) else if constexpr (CSameAs<FCharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -440,7 +440,7 @@ struct TChar
return false; 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.")); 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)); 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.")); 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)); 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; 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(""); NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isspace(InChar, Loc); return NAMESPACE_STD::isspace(InChar, Loc);
} }
else if constexpr (CSameAs<CharType, u8char>) else if constexpr (CSameAs<FCharType, u8char>)
{ {
/* /*
* ISO/IEC 6429 * ISO/IEC 6429
@ -488,7 +488,7 @@ struct TChar
return false; return false;
} }
else if constexpr (CSameAs<CharType, u16char>) else if constexpr (CSameAs<FCharType, u16char>)
{ {
/* /*
* ISO/IEC 6429 * ISO/IEC 6429
@ -533,7 +533,7 @@ struct TChar
return false; return false;
} }
else if constexpr (CSameAs<CharType, u32char>) else if constexpr (CSameAs<FCharType, u32char>)
{ {
/* /*
* ISO/IEC 6429 * ISO/IEC 6429
@ -578,26 +578,26 @@ struct TChar
return false; return false;
} }
else static_assert(sizeof(CharType) == -1, "Unsupported character type"); else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
return false; 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(""); NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isblank(InChar, Loc); return NAMESPACE_STD::isblank(InChar, Loc);
} }
else if constexpr (CSameAs<CharType, u8char>) else if constexpr (CSameAs<FCharType, u8char>)
{ {
/* <U0009>;<U0020>; */ /* <U0009>;<U0020>; */
return InChar == U8TEXT('\u0009') || InChar == U8TEXT('\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>; */ /* <U0009>;<U0020>;<U1680>;<U180E>;<U2000>..<U2006>;<U2008>..<U200A>;<U205F>;<U3000>; */
return return
@ -608,7 +608,7 @@ struct TChar
(InChar == U16TEXT('\u205F') || InChar == U16TEXT('\u3000')); (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>; */ /* <U0009>;<U0020>;<U1680>;<U180E>;<U2000>..<U2006>;<U2008>..<U200A>;<U205F>;<U3000>; */
return return
@ -619,20 +619,20 @@ struct TChar
(InChar == U32TEXT('\u205F') || InChar == U32TEXT('\u3000')); (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; 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(""); NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::isprint(InChar, Loc); return NAMESPACE_STD::isprint(InChar, Loc);
} }
else if constexpr (CSameAs<CharType, u8char>) else if constexpr (CSameAs<FCharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -643,7 +643,7 @@ struct TChar
return false; 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.")); 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)); 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.")); 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)); 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; 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(""); NAMESPACE_STD::locale Loc("");
return NAMESPACE_STD::ispunct(InChar, Loc); return NAMESPACE_STD::ispunct(InChar, Loc);
} }
else if constexpr (CSameAs<CharType, u8char>) else if constexpr (CSameAs<FCharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -689,7 +689,7 @@ struct TChar
return false; 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.")); 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)); 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.")); 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)); 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; 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(""); 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 * BASIC LATIN
@ -737,7 +737,7 @@ struct TChar
return InChar; 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.")); 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))); 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.")); 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))); 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; 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(""); 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 * BASIC LATIN
@ -785,7 +785,7 @@ struct TChar
return InChar; 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.")); 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))); 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.")); 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))); 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; return InChar;
} }
NODISCARD FORCEINLINE static constexpr unsigned ToDigit(CharType InChar) NODISCARD FORCEINLINE static constexpr unsigned ToDigit(FCharType InChar)
{ {
static_assert(TChar::IsASCII()); static_assert(TChar::IsASCII());
@ -834,12 +834,12 @@ struct TChar
static_assert(sizeof(DigitFromChar) == 256); 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]; 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()); static_assert(TChar::IsASCII());
@ -867,7 +867,7 @@ struct TChar
static_assert(sizeof(DigitFromChar) == 256); 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]; return DigitFromChar[InChar];
} }
@ -894,25 +894,25 @@ struct TChar
static_assert(sizeof(DigitFromChar) == 256); 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]; 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].")); 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].")); 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) static bool Do(auto& Result, auto& Object, auto Param)
{ {
// ReSharper disable once CppInconsistentNaming
using U = TRemoveCVRef<decltype(Object)>; using U = TRemoveCVRef<decltype(Object)>;
if constexpr (!CConst<TRemoveReference<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; bool bNegative = false;
@ -1077,11 +1078,11 @@ struct TStringObjectFormatter
{ {
bNegative = true; 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]; T Buffer[BufferSize];
@ -1111,8 +1112,8 @@ struct TStringObjectFormatter
case 6: case 6:
case 7: case 7:
case 9: case 9:
case 10: do { *--Iter = static_cast<T>('0' + 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, bLowercase); Unsigned = static_cast<UnsignedU>(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 else
@ -1130,12 +1131,12 @@ struct TStringObjectFormatter
case 6: case 6:
case 7: case 7:
case 9: case 9:
case 10: do { *--Iter = static_cast<T>('0' + 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<UnsignedU>(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; T* DigitBegin = Iter;
@ -1144,7 +1145,7 @@ struct TStringObjectFormatter
{ {
const size_t Padding = Param.Padding - (DigitEnd - DigitBegin); 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. // Append the prefix to the buffer.
@ -1171,7 +1172,7 @@ struct TStringObjectFormatter
{ {
const size_t Padding = Param.Padding - (DigitEnd - DigitBegin); 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); Result.Reserve(Result.Num() + (DigitBegin - Iter) + Param.Padding);
@ -1349,6 +1350,7 @@ struct TStringObjectParser
{ {
static bool Do(auto& View, auto& Object, auto Param) static bool Do(auto& View, auto& Object, auto Param)
{ {
// ReSharper disable once CppInconsistentNaming
using U = TRemoveCVRef<decltype(Object)>; using U = TRemoveCVRef<decltype(Object)>;
if constexpr (CConst<TRemoveReference<decltype(Object)>>) if constexpr (CConst<TRemoveReference<decltype(Object)>>)
@ -2200,17 +2202,17 @@ struct TStringObjectParser
return TChar<T>::ToDigit(Char); return TChar<T>::ToDigit(Char);
}; };
using UnsignedU = TMakeUnsigned<U>; using FUnsignedU = TMakeUnsigned<U>;
// The limit value that can be stored in an unsigned integer. // 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. // The limit value that can be stored in a signed integer.
constexpr U SignedMaximum = static_cast<U>(UnsignedMaximum >> 1); constexpr U SignedMaximum = static_cast<U>(UnsignedMaximum >> 1);
constexpr U SignedMinimum = -static_cast<U>(SignedMaximum) - 1; constexpr U SignedMinimum = -static_cast<U>(SignedMaximum) - 1;
UnsignedU LastValue = 0; FUnsignedU LastValue = 0;
UnsignedU Unsigned = 0; FUnsignedU Unsigned = 0;
if (TrimmedView.IsEmpty()) return false; if (TrimmedView.IsEmpty()) return false;
@ -2223,7 +2225,7 @@ struct TStringObjectParser
TrimmedView.RemovePrefix(1); TrimmedView.RemovePrefix(1);
Unsigned = static_cast<UnsignedU>(Digit); Unsigned = static_cast<FUnsignedU>(Digit);
while (!TrimmedView.IsEmpty()) while (!TrimmedView.IsEmpty())
{ {
@ -2235,7 +2237,7 @@ struct TStringObjectParser
LastValue = Unsigned; LastValue = Unsigned;
Unsigned = static_cast<UnsignedU>(LastValue * Base + Digit); Unsigned = static_cast<FUnsignedU>(LastValue * Base + Digit);
if (Unsigned < LastValue) return false; if (Unsigned < LastValue) return false;
} }
@ -2245,11 +2247,11 @@ struct TStringObjectParser
if constexpr (CSigned<U>) if constexpr (CSigned<U>)
{ {
// Handle overflow. // Handle overflow.
if (!bNegative && Unsigned >= static_cast<UnsignedU>(SignedMaximum)) return false; if (!bNegative && Unsigned >= static_cast<FUnsignedU>(SignedMaximum)) return false;
if ( bNegative && Unsigned >= static_cast<UnsignedU>(SignedMinimum)) return false; if ( bNegative && Unsigned >= static_cast<FUnsignedU>(SignedMinimum)) return false;
// Handle negative sign. // Handle negative sign.
if (bNegative) Unsigned = static_cast<UnsignedU>(-Unsigned); if (bNegative) Unsigned = static_cast<FUnsignedU>(-Unsigned);
} }
Object = static_cast<U>(Unsigned); Object = static_cast<U>(Unsigned);
@ -2705,14 +2707,14 @@ NAMESPACE_PRIVATE_END
template <CCharType T, CAllocator<T> Allocator> template <CCharType T, CAllocator<T> Allocator>
template <typename ... Ts> 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. // The Unreal Engine says that the starting buffer size catches 99.97% of printf calls.
constexpr size_t ReserveBufferSize = 512; constexpr size_t ReserveBufferSize = 512;
TString<T, TInlineAllocator<ReserveBufferSize>> Result; 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()); Append(Result.Begin(), Result.End());
} }
@ -2721,13 +2723,13 @@ template <CCharType T>
template <typename ... Ts> template <typename ... Ts>
size_t TStringView<T>::ParseAndTrim(TStringView Fmt, Ts&... Args) 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> template <CCharType T, CAllocator<T> Allocator>
void TString<T, Allocator>::AppendBool(bool Value) 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> template <CCharType T, CAllocator<T> Allocator>
@ -2738,13 +2740,13 @@ void TString<T, Allocator>::AppendInt(U Value, unsigned Base)
struct { unsigned Base; } Param = { 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>) template <CCharType T, CAllocator<T> Allocator> template <CFloatingPoint U> requires (!CConst<U> && !CVolatile<U>)
void TString<T, Allocator>::AppendFloat(U Value) 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>) 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 }; 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>) 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 }; 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> template <CCharType T>
@ -2768,9 +2770,9 @@ constexpr bool TStringView<T>::ToBoolAndTrim()
{ {
bool Value = false; 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; Value = IntValue != 0;
} }
@ -2789,7 +2791,7 @@ constexpr U TStringView<T>::ToIntAndTrim(unsigned Base)
struct { unsigned Base; } Param = { Base }; struct { unsigned Base; } Param = { Base };
NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, Value, Param); NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, Value, Param);
return Value; return Value;
} }
@ -2802,7 +2804,7 @@ constexpr U TStringView<T>::ToFloatAndTrim(bool bFixed, bool bScientific)
struct { bool bFixed; bool bScientific; } Param = { bFixed, 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; return Value;
} }

View File

@ -35,33 +35,33 @@ class TString : public TArray<T, Allocator>
{ {
private: private:
using Super = TArray<T, Allocator>; using FSuper = TArray<T, Allocator>;
public: public:
using ElementType = typename Super::ElementType; using FElementType = typename FSuper::FElementType;
using AllocatorType = typename Super::AllocatorType; using FAllocatorType = typename FSuper::FAllocatorType;
using Reference = typename Super:: Reference; using FReference = typename FSuper:: FReference;
using ConstReference = typename Super::ConstReference; using FConstReference = typename FSuper::FConstReference;
using Iterator = typename Super:: Iterator; using FIterator = typename FSuper:: FIterator;
using ConstIterator = typename Super::ConstIterator; using FConstIterator = typename FSuper::FConstIterator;
using ReverseIterator = typename Super:: ReverseIterator; using FReverseIterator = typename FSuper:: FReverseIterator;
using ConstReverseIterator = typename Super::ConstReverseIterator; using FConstReverseIterator = typename FSuper::FConstReverseIterator;
static_assert(CContiguousIterator< Iterator>); static_assert(CContiguousIterator< FIterator>);
static_assert(CContiguousIterator<ConstIterator>); static_assert(CContiguousIterator<FConstIterator>);
/** Default constructor. Constructs an empty string. */ /** Default constructor. Constructs an empty string. */
FORCEINLINE TString() = default; FORCEINLINE TString() = default;
/** Constructs the string with 'Count' copies of characters with 'InValue'. */ /** 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'). */ /** 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.")); 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; FORCEINLINE TString(nullptr_t, size_t) = delete;
/** Constructs a string with the contents of the range ['InPtr', '\0'). */ /** 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.")); checkf(InPtr != nullptr, TEXT("TString cannot be initialized by nullptr. Please check the pointer."));
} }
@ -77,11 +77,11 @@ public:
FORCEINLINE TString(nullptr_t) = delete; FORCEINLINE TString(nullptr_t) = delete;
/** Constructs the string with the contents of the 'View'. */ /** 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'). */ /** Constructs the string 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(I First, S Last) : Super(MoveTemp(First), MoveTemp(Last)) { } FORCEINLINE TString(I First, S Last) : FSuper(MoveTemp(First), MoveTemp(Last)) { }
/** Copy constructor. Constructs the string with the copy of the contents of 'InValue'. */ /** Copy constructor. Constructs the string with the copy of the contents of 'InValue'. */
FORCEINLINE TString(const TString&) = default; FORCEINLINE TString(const TString&) = default;
@ -90,7 +90,7 @@ public:
FORCEINLINE TString(TString&&) = default; FORCEINLINE TString(TString&&) = default;
/** Constructs the string with the contents of the initializer list. */ /** 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'. */ /** Copy assignment operator. Replaces the contents with a copy of the contents of 'InValue'. */
FORCEINLINE TString& operator=(const TString&) = default; FORCEINLINE TString& operator=(const TString&) = default;
@ -99,27 +99,27 @@ public:
FORCEINLINE TString& operator=(TString&&) = default; FORCEINLINE TString& operator=(TString&&) = default;
/** Compares the contents of two strings. */ /** 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. */ /** 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, FElementType RHS) { return TStringView<FElementType>(LHS) == RHS; }
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, const ElementType* RHS) { return TStringView<ElementType>(LHS) == RHS; } NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, const FElementType* RHS) { return TStringView<FElementType>(LHS) == RHS; }
NODISCARD friend FORCEINLINE bool operator==( ElementType LHS, const TString& RHS) { return LHS == TStringView<ElementType>(RHS); } NODISCARD friend FORCEINLINE bool operator==( FElementType LHS, const TString& RHS) { return LHS == TStringView<FElementType>(RHS); }
NODISCARD friend FORCEINLINE bool operator==(const ElementType* LHS, const TString& RHS) { return LHS == TStringView<ElementType>(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. */ /** 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. */ /** 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, FElementType RHS) { return TStringView<FElementType>(LHS) <=> RHS; }
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, const ElementType* RHS) { return TStringView<ElementType>(LHS) <=> RHS; } NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, const FElementType* RHS) { return TStringView<FElementType>(LHS) <=> RHS; }
NODISCARD friend FORCEINLINE auto operator<=>( ElementType LHS, const TString& RHS) { return LHS <=> TStringView<ElementType>(RHS); } NODISCARD friend FORCEINLINE auto operator<=>( FElementType LHS, const TString& RHS) { return LHS <=> TStringView<FElementType>(RHS); }
NODISCARD friend FORCEINLINE auto operator<=>(const ElementType* LHS, const TString& RHS) { return LHS <=> TStringView<ElementType>(RHS); } NODISCARD friend FORCEINLINE auto operator<=>(const FElementType* LHS, const TString& RHS) { return LHS <=> TStringView<FElementType>(RHS); }
public: public:
/** Inserts 'InValue' before 'Index' in the string. */ /** 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().")); checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
@ -127,15 +127,15 @@ public:
} }
/** Inserts 'InValue' before 'Iter' in the string. */ /** 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().")); 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. */ /** 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().")); 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. */ /** 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().")); 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. */ /** 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().")); 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. */ /** 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().")); 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. */ /** Inserts characters from the range ['First', 'Last') before 'Index' in the string. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
FORCEINLINE Iterator Insert(size_t Index, I First, S Last) FORCEINLINE FIterator Insert(size_t Index, I First, S Last)
{ {
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num().")); 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'. */ /** Inserts characters from the range ['First', 'Last') before 'Iter'. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
FORCEINLINE Iterator Insert(ConstIterator Iter, I First, S Last) FORCEINLINE FIterator Insert(FConstIterator Iter, I First, S Last)
{ {
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator().")); 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. */ /** 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().")); 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. */ /** 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().")); 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. */ /** 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().")); 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. */ /** 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().")); 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. */ /** 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.")); 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. */ /** 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().")); 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'. */ /** Here, the 'Erase' is already stable and there is no need to provide 'StableErase'. */
void StableErase(...) = delete; void StableErase(...) = delete;
/** Appends 'Count' copies of the 'InValue' to the end of the string. */ /** 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. */ /** 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. */ /** 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) TString& Append(I First, S Last)
{ {
if constexpr (CForwardIterator<I>) if constexpr (CForwardIterator<I>)
@ -258,7 +258,7 @@ public:
for (size_t Index = CurrentNum; Index != CurrentNum + Count; ++Index) for (size_t Index = CurrentNum; Index != CurrentNum + Count; ++Index)
{ {
(*this)[Index] = ElementType(*First++); (*this)[Index] = FElementType(*First++);
} }
} }
else else
@ -270,40 +270,40 @@ public:
} }
/** Appends the contents of the initializer list to the end of the string. */ /** 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. */ /** 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. */ /** 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. */ /** 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. */ /** Concatenates two strings. */
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, const TString& RHS) { return TString(LHS).Append(RHS); } NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, const TString& RHS) { return TString(LHS).Append(RHS); }
/** Concatenates the string with the given character value. */ /** 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, FElementType 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, const FElementType* 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+(const TString& LHS, TStringView<FElementType> 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+( FElementType 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+( const FElementType* 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+(TStringView<FElementType> LHS, const TString& RHS) { return TString( LHS).Append(RHS); }
/** Concatenates two strings. The rvalue maybe modified. */ /** Concatenates two strings. The rvalue maybe modified. */
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, TString&& RHS) { LHS.Append(MoveTemp(RHS)); return LHS; } NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, TString&& RHS) { LHS.Append(MoveTemp(RHS)); return LHS; }
/** Concatenates two strings. The rvalue maybe modified. */ /** 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, FElementType 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, const FElementType* 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, TStringView<FElementType> 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+(TString&& LHS, const TString<FElementType>& 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+( FElementType 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+( const FElementType* 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+( TStringView<FElementType> 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+(const TString<FElementType>& LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
public: public:
@ -330,7 +330,7 @@ public:
/** Removes whitespace characters from the start of this string. */ /** Removes whitespace characters from the start of this string. */
FORCEINLINE constexpr TString& TrimStart(bool bAllowShrinking = true) 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) if (Index != INDEX_NONE)
{ {
@ -344,7 +344,7 @@ public:
/** Removes whitespace characters from the end of this string. */ /** Removes whitespace characters from the end of this string. */
FORCEINLINE constexpr TString& TrimEnd(bool bAllowShrinking = true) 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) if (Index != INDEX_NONE)
{ {
@ -367,7 +367,7 @@ public:
/** Removes characters after the first null-terminator. */ /** Removes characters after the first null-terminator. */
FORCEINLINE constexpr TString& TrimToNullTerminator(bool bAllowShrinking = true) FORCEINLINE constexpr TString& TrimToNullTerminator(bool bAllowShrinking = true)
{ {
auto Index = Find(LITERAL(ElementType, '\0')); auto Index = Find(LITERAL(FElementType, '\0'));
if (Index != INDEX_NONE) if (Index != INDEX_NONE)
{ {
@ -380,50 +380,50 @@ public:
public: public:
/** @return true if the string view starts with the given prefix, false otherwise. */ /** @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. */ /** @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. */ /** @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. */ /** @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. */ /** @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. */ /** @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. */ /** @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 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'. */ /** 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.")); 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'. */ /** 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().")); 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'. */ /** 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.")); 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'. */ /** 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().")); 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'). */ /** 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) 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.")); 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'). */ /** Replace the substring ['First', 'Last') with the contents of the range ['InString', 'Sentinel'). */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
TString& Replace(ConstIterator First, ConstIterator Last, I InString, S Sentinel) 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().")); 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) 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) for (size_t Index = InsertIndex + InsertCount; Index != NumToReset; ++Index)
@ -505,7 +505,7 @@ public:
for (size_t Index = InsertIndex; Index != InsertIndex + InsertCount; ++Index) 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. */ /** 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.")); 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. */ /** 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().")); 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.")); 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. */ /** 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(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.")); 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; 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. */ /** @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.")); 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. */ /** @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.")); 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. */ /** @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 NODISCARD size_t Find(F&& InPredicate, size_t Index = 0) const
{ {
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index.")); 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. */ /** @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.")); 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. */ /** @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.")); 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. */ /** @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 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.")); 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. */ /** @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.")); 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. */ /** @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.")); 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. */ /** @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.")); 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. */ /** @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.")); 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. */ /** @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.")); 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. */ /** @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.")); 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. */ /** @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.")); 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. */ /** @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.")); 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: public:
@ -1028,7 +1028,7 @@ public:
{ {
if (this->Max() >= this->Num() + 1) 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); return *TStringView(this->GetData(), this->Num() + 1);
} }
@ -1052,31 +1052,31 @@ public:
/** @return true if the string only contains valid characters, false otherwise. */ /** @return true if the string only contains valid characters, false otherwise. */
NODISCARD FORCEINLINE bool IsValid() const 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. */ /** @return true if the string only contains ASCII characters, false otherwise. */
NODISCARD FORCEINLINE bool IsASCII() const 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. */ /** @return true if the string can be fully represented as a boolean value, false otherwise. */
NODISCARD FORCEINLINE bool IsBoolean() const 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. */ /** @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 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. */ /** @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 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: public:
@ -1202,7 +1202,7 @@ public:
*/ */
NODISCARD FORCEINLINE bool ToBool() const 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.")); 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>) template <CFloatingPoint U = float> requires (!CConst<U> && !CVolatile<U>)
NODISCARD FORCEINLINE U ToFloat(bool bFixed = true, bool bScientific = false) const 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. */ /** Converts a string into a boolean value and remove the parsed substring. */
NODISCARD FORCEINLINE bool ToBoolAndTrim() NODISCARD FORCEINLINE bool ToBoolAndTrim()
{ {
TStringView<ElementType> View = *this; TStringView<FElementType> View = *this;
bool Result = View.ToBoolAndTrim(); bool Result = View.ToBoolAndTrim();
@ -1265,7 +1265,7 @@ public:
template <CIntegral U = int> requires (!CSameAs<U, bool> && !CConst<U> && !CVolatile<U>) template <CIntegral U = int> requires (!CSameAs<U, bool> && !CConst<U> && !CVolatile<U>)
NODISCARD FORCEINLINE U ToIntAndTrim(unsigned Base = 10) NODISCARD FORCEINLINE U ToIntAndTrim(unsigned Base = 10)
{ {
TStringView<ElementType> View = *this; TStringView<FElementType> View = *this;
U Result = View.template ToIntAndTrim<U>(Base); U Result = View.template ToIntAndTrim<U>(Base);
@ -1280,7 +1280,7 @@ public:
template <CFloatingPoint U = float> requires (!CConst<U> && !CVolatile<U>) template <CFloatingPoint U = float> requires (!CConst<U> && !CVolatile<U>)
NODISCARD FORCEINLINE U ToFloatAndTrim(bool bFixed = true, bool bScientific = true) 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); U Result = View.template ToFloatAndTrim<U>(bFixed, bScientific);
@ -1302,7 +1302,7 @@ public:
* @return The formatted string containing the objects. * @return The formatted string containing the objects.
*/ */
template <typename... Ts> 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; TString Result;
@ -1313,7 +1313,7 @@ public:
/** Format some objects using a format string and append to the string. */ /** Format some objects using a format string and append to the string. */
template <typename... Ts> 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. * Parse a string using a format string to objects.
@ -1324,16 +1324,16 @@ public:
* @return The number of objects successfully parsed. * @return The number of objects successfully parsed.
*/ */
template <typename... Ts> 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...); return TStringView(*this).Parse(Fmt, Args...);
} }
/** Parse a string using a format string to objects and remove the parsed substring. */ /** Parse a string using a format string to objects and remove the parsed substring. */
template <typename... Ts> 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...); size_t Result = View.ParseAndTrim(Fmt, Args...);
@ -1347,10 +1347,10 @@ public:
public: public:
/** Overloads the GetTypeHash algorithm for TString. */ /** 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. */ /** 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 FU32String = TString<u32char>;
using FUnicodeString = TString<unicodechar>; 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()) { } : TStringView(InString.GetData(), InString.Num()) { }
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)

View File

@ -82,36 +82,36 @@ class TStringView : public TArrayView<const T>
{ {
private: private:
using Super = TArrayView<const T>; using FSuper = TArrayView<const T>;
public: public:
using ElementType = T; using FElementType = T;
using Reference = typename Super::Reference; using FReference = typename FSuper::FReference;
using Iterator = typename Super::Iterator; using FIterator = typename FSuper:: FIterator;
using ReverseIterator = typename Super::ReverseIterator; using FReverseIterator = typename FSuper::FReverseIterator;
static_assert(CContiguousIterator<Iterator>); static_assert(CContiguousIterator<FIterator>);
/** Constructs an empty string view. */ /** Constructs an empty string view. */
FORCEINLINE constexpr TStringView() = default; FORCEINLINE constexpr TStringView() = default;
/** Constructs a string view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */ /** Constructs a string view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */
template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const ElementType(*)[]>) template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const FElementType(*)[]>)
FORCEINLINE constexpr TStringView(I InFirst, size_t InCount) : Super(InFirst, InCount) { } FORCEINLINE constexpr TStringView(I InFirst, size_t InCount) : FSuper(InFirst, InCount) { }
/** Constructs a string view that is a view over the range ['InFirst', 'InLast'). */ /** 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(*)[]>) template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const FElementType(*)[]>)
FORCEINLINE constexpr TStringView(I InFirst, S InLast) : Super(InFirst, InLast) { } FORCEINLINE constexpr TStringView(I InFirst, S InLast) : FSuper(InFirst, InLast) { }
/** Constructs a string view that is a view over the string 'InString'. */ /** Constructs a string view that is a view over the string 'InString'. */
template <typename Allocator> 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'). */ /** 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.")); 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; FORCEINLINE constexpr TStringView(nullptr_t, size_t) = delete;
/** Constructs a string view that is a view over the range ['InPtr', '\0'). */ /** 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.")); checkf(InPtr != nullptr, TEXT("TStringView cannot be initialized by nullptr. Please check the pointer."));
size_t Length = 0; size_t Length = 0;
if constexpr (CSameAs<ElementType, char>) if constexpr (CSameAs<FElementType, char>)
{ {
Length = NAMESPACE_STD::strlen(InPtr); Length = NAMESPACE_STD::strlen(InPtr);
} }
else if constexpr (CSameAs<ElementType, wchar>) else if constexpr (CSameAs<FElementType, wchar>)
{ {
Length = NAMESPACE_STD::wcslen(InPtr); Length = NAMESPACE_STD::wcslen(InPtr);
} }
else else
{ {
while (InPtr[Length] != LITERAL(ElementType, '\0')) ++Length; while (InPtr[Length] != LITERAL(FElementType, '\0')) ++Length;
} }
*this = TStringView(InPtr, Length); *this = TStringView(InPtr, Length);
@ -150,18 +150,18 @@ public:
FORCEINLINE constexpr TStringView& operator=(const TStringView&) noexcept = default; FORCEINLINE constexpr TStringView& operator=(const TStringView&) noexcept = default;
/** Compares the contents of two string views. */ /** 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. */ /** 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==(TStringView LHS, FElementType 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==(FElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) == RHS; }
/** Compares the contents of two string views. */ /** 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. */ /** 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<=>(TStringView LHS, FElementType 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<=>(FElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) <=> RHS; }
public: public:
@ -188,7 +188,7 @@ public:
/** Removes whitespace characters from the start of this string. */ /** Removes whitespace characters from the start of this string. */
FORCEINLINE constexpr TStringView& TrimStart() 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) if (Index != INDEX_NONE)
{ {
@ -202,7 +202,7 @@ public:
/** Removes whitespace characters from the end of this string. */ /** Removes whitespace characters from the end of this string. */
FORCEINLINE constexpr TStringView& TrimEnd() 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) if (Index != INDEX_NONE)
{ {
@ -225,7 +225,7 @@ public:
/** Removes characters after the first null-terminator. */ /** Removes characters after the first null-terminator. */
FORCEINLINE constexpr TStringView& TrimToNullTerminator() FORCEINLINE constexpr TStringView& TrimToNullTerminator()
{ {
auto Index = Find(LITERAL(ElementType, '\0')); auto Index = Find(LITERAL(FElementType, '\0'));
if (Index != INDEX_NONE) if (Index != INDEX_NONE)
{ {
@ -238,7 +238,7 @@ public:
public: public:
/** Copies the elements of this string view to the destination buffer without null-termination. */ /** 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.")); 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.")); 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()); return TStringView(Temp.GetData(), Temp.Num());
} }
@ -289,7 +289,7 @@ public:
} }
/** @return true if the string view starts with the given prefix, false otherwise. */ /** @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; 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. */ /** @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; return this->Num() >= 1 && this->Back() == Suffix;
} }
@ -313,13 +313,13 @@ public:
} }
/** @return true if the string view contains the given character, false otherwise. */ /** @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 Find(Char) != INDEX_NONE;
} }
/** @return true if the string view contains character that satisfy the given predicate, false otherwise. */ /** @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 NODISCARD FORCEINLINE constexpr bool Contains(F&& InPredicate) const
{ {
return Find(Forward<F>(InPredicate)) != INDEX_NONE; 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. */ /** @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; 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. */ /** @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 NODISCARD constexpr size_t Find(F&& InPredicate, size_t Index = 0) const
{ {
if (Index >= this->Num()) return INDEX_NONE; 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. */ /** @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; 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. */ /** @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 NODISCARD constexpr size_t RFind(F&& InPredicate, size_t Index = INDEX_NONE) const
{ {
if (Index != INDEX_NONE && Index >= this->Num()) return INDEX_NONE; 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. */ /** @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 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. */ /** @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); 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. */ /** @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 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. */ /** @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); 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. */ /** @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 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. */ /** @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. */ /** @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 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. */ /** @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: public:
@ -490,18 +490,18 @@ public:
/** @return The non-modifiable standard C character string version of the string view. */ /** @return The non-modifiable standard C character string version of the string view. */
NODISCARD FORCEINLINE auto operator*() const 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); 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: public:
@ -509,9 +509,9 @@ public:
/** @return true if the string only contains valid characters, false otherwise. */ /** @return true if the string only contains valid characters, false otherwise. */
NODISCARD constexpr bool IsValid() const 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; return true;
@ -520,9 +520,9 @@ public:
/** @return true if the string only contains ASCII characters, false otherwise. */ /** @return true if the string only contains ASCII characters, false otherwise. */
NODISCARD constexpr bool IsASCII() const 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; return true;
@ -543,7 +543,7 @@ public:
{ {
TStringView View = *this; TStringView View = *this;
if (View.StartsWith(LITERAL(ElementType, '-'))) if (View.StartsWith(LITERAL(FElementType, '-')))
{ {
if (bSigned) View.RemovePrefix(1); if (bSigned) View.RemovePrefix(1);
else return false; else return false;
@ -559,7 +559,7 @@ public:
{ {
TStringView View = *this; TStringView View = *this;
if (View.StartsWith(LITERAL(ElementType, '-'))) if (View.StartsWith(LITERAL(FElementType, '-')))
{ {
if (bSigned) View.RemovePrefix(1); if (bSigned) View.RemovePrefix(1);
else return false; else return false;
@ -659,7 +659,7 @@ public:
public: public:
/** Overloads the GetTypeHash algorithm for TStringView. */ /** 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 FU32StringView = TStringView<u32char>;
using FUnicodeStringView = TStringView<unicodechar>; using FUnicodeStringView = TStringView<unicodechar>;
// ReSharper disable CppInconsistentNaming
#define TEXT_VIEW(X) TStringView(TEXT(X)) #define TEXT_VIEW(X) TStringView(TEXT(X))
#define WTEXT_VIEW(X) TStringView(WTEXT(X)) #define WTEXT_VIEW(X) TStringView(WTEXT(X))
#define U8TEXT_VIEW(X) TStringView(U8TEXT(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)) #define LITERAL_VIEW(T, X) TStringView(LITERAL(T, X))
// ReSharper restore CppInconsistentNaming
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END 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 // 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. // instead of directly calling the assignment operation of the contained value.
// The purpose of this is as follows: // The purpose of this is as follows:
// 1) the copy assignment might not exist. // 1) the copy assignment might not exist.
// 2) the typical case is that the objects are different. // 2) the typical case is that the objects are different.
// 3) it is less exception-safe // 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. // 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)...); 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).... */ /** 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&&...>) 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) FORCEINLINE explicit FAny(TInPlaceType<T>, initializer_list<U> IL, Ts&&... Args)
@ -244,23 +244,23 @@ public:
&& NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, T&&>) && NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, T&&>)
FORCEINLINE FAny& operator=(T&& InValue) 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; return *this;
} }
} }
Destroy(); Destroy();
EmplaceImpl<DecayedType>(Forward<T>(InValue)); EmplaceImpl<FDecayedType>(Forward<T>(InValue));
return *this; return *this;
} }
/** Check if the contained value is equivalent to 'InValue'. */ /** Check if the contained value is equivalent to 'InValue'. */
template <typename T> requires (!CSameAs<FAny, TRemoveCVRef<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CEqualityComparable<T>) template <typename T> requires (!CSameAs<FAny, TRemoveCVRef<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CEqualityComparable<T>)
NODISCARD FORCEINLINE constexpr bool operator==(const T& InValue) const& NODISCARD FORCEINLINE constexpr bool operator==(const T& InValue) const&
@ -352,12 +352,12 @@ public:
Destroy(); Destroy();
Invalidate(); Invalidate();
} }
/** Overloads the Swap algorithm for FAny. */ /** Overloads the Swap algorithm for FAny. */
friend void Swap(FAny& A, FAny& B) friend void Swap(FAny& A, FAny& B)
{ {
if (!A.IsValid() && !B.IsValid()) return; if (!A.IsValid() && !B.IsValid()) return;
if (A.IsValid() && !B.IsValid()) if (A.IsValid() && !B.IsValid())
{ {
B = MoveTemp(A); B = MoveTemp(A);
@ -524,7 +524,7 @@ private:
default: check_no_entry(); return nullptr; default: check_no_entry(); return nullptr;
} }
} }
FORCEINLINE const void* GetStorage() const FORCEINLINE const void* GetStorage() const
{ {
switch (GetRepresentation()) switch (GetRepresentation())
@ -536,36 +536,36 @@ private:
default: check_no_entry(); return nullptr; default: check_no_entry(); return nullptr;
} }
} }
template <typename T, typename... Ts> template <typename T, typename... Ts>
void EmplaceImpl(Ts&&... Args) 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 bIsTriviallyStorable = sizeof(FDecayedType) <= sizeof(TrivialStorage.Internal) && alignof(FDecayedType) <= alignof(FAny) && CTriviallyCopyable<FDecayedType>;
constexpr bool bIsSmallStorable = sizeof(DecayedType) <= sizeof( SmallStorage.Internal) && alignof(DecayedType) <= alignof(FAny); 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) if constexpr (bIsTriviallyStorable)
{ {
new (&TrivialStorage.Internal) DecayedType(Forward<Ts>(Args)...); new (&TrivialStorage.Internal) FDecayedType(Forward<Ts>(Args)...);
TypeInfo |= static_cast<uintptr>(ERepresentation::Trivial); TypeInfo |= static_cast<uintptr>(ERepresentation::Trivial);
} }
else if constexpr (bIsSmallStorable) else if constexpr (bIsSmallStorable)
{ {
new (&SmallStorage.Internal) DecayedType(Forward<Ts>(Args)...); new (&SmallStorage.Internal) FDecayedType(Forward<Ts>(Args)...);
SmallStorage.RTTI = &SelectedRTTI; SmallStorage.RTTI = &SelectedRTTI;
TypeInfo |= static_cast<uintptr>(ERepresentation::Small); TypeInfo |= static_cast<uintptr>(ERepresentation::Small);
} }
else else
{ {
BigStorage.External = Memory::Malloc(sizeof(DecayedType), alignof(DecayedType)); BigStorage.External = Memory::Malloc(sizeof(FDecayedType), alignof(FDecayedType));
new (BigStorage.External) DecayedType(Forward<Ts>(Args)...); new (BigStorage.External) FDecayedType(Forward<Ts>(Args)...);
BigStorage.RTTI = &SelectedRTTI; BigStorage.RTTI = &SelectedRTTI;
TypeInfo |= static_cast<uintptr>(ERepresentation::Big); 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 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 * 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. * 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 * @see https://en.cppreference.com/w/cpp/atomic/memory_order
*/ */
enum class EMemoryOrder : uint8 enum class EMemoryOrder : uint8
@ -68,48 +68,48 @@ struct TAtomicImpl : FSingleton
{ {
protected: 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: public:
using ValueType = T; using FValueType = T;
/** Indicates that the type is always lock-free */ /** 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. */ /** Indicates the required alignment of an object to be referenced by TAtomicRef. */
static constexpr size_t RequiredAlignment = NAMESPACE_STD::atomic_ref<T>::required_alignment; static constexpr size_t RequiredAlignment = NAMESPACE_STD::atomic_ref<T>::required_alignment;
/** Constructs an atomic object. */ /** Constructs an atomic object. */
FORCEINLINE constexpr TAtomicImpl() requires (!bIsRef) : NativeAtomic() { }; FORCEINLINE constexpr TAtomicImpl() requires (!bIsRef) : NativeAtomic() { }
FORCEINLINE constexpr TAtomicImpl(ValueType Desired) requires (!bIsRef) : NativeAtomic(Desired) { }; FORCEINLINE constexpr TAtomicImpl(FValueType Desired) requires (!bIsRef) : NativeAtomic(Desired) { }
/** Constructs an atomic reference. */ /** Constructs an atomic reference. */
FORCEINLINE explicit TAtomicImpl(ValueType& Desired) requires (bIsRef) : NativeAtomic(Desired) { check(Memory::IsAligned(&Desired, RequiredAlignment)); }; FORCEINLINE explicit TAtomicImpl(FValueType& Desired) requires (bIsRef) : NativeAtomic(Desired) { check(Memory::IsAligned(&Desired, RequiredAlignment)); }
FORCEINLINE TAtomicImpl(TAtomicImpl& InValue) requires (bIsRef) : NativeAtomic(InValue) { }; FORCEINLINE TAtomicImpl(TAtomicImpl& InValue) requires (bIsRef) : NativeAtomic(InValue) { }
/** Stores a value into an atomic object. */ /** Stores a value into an atomic object. */
FORCEINLINE ValueType operator=(ValueType Desired) { return NativeAtomic = Desired; } FORCEINLINE FValueType operator=(FValueType Desired) { return NativeAtomic = Desired; }
FORCEINLINE ValueType operator=(ValueType Desired) volatile requires (bIsAlwaysLockFree) { 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. */ /** 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(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(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) 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. */ /** 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 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 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 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. */ /** Loads a value from an atomic object. */
NODISCARD FORCEINLINE operator ValueType() const { return static_cast<ValueType>(NativeAtomic); } NODISCARD FORCEINLINE operator FValueType() const { return static_cast<FValueType>(NativeAtomic); }
NODISCARD FORCEINLINE operator ValueType() const volatile requires (bIsAlwaysLockFree) { return static_cast<ValueType>(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. */ /** 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 FValueType Exchange(FValueType 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) 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. */ /** 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); 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)); 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. */ /** 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); 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)); 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. */ /** 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)); 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)); 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. */ /** 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)); 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)); 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. */ /** 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(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(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) 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. */ /** 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) { 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(); } 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. */ /** 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>) template <typename F> requires (CInvocableResult<FValueType, F, FValueType>)
FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) 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. // 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; return Temp;
} }
/** Atomically executes the 'Func' on the value stored in the atomic object and obtains the value held previously. */ /** 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) template <typename F> requires (CInvocableResult<FValueType, F, FValueType> && bIsAlwaysLockFree)
FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile 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. // 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; return Temp;
} }
/** Atomically adds the argument to the value stored in the atomic object and obtains the value held previously. */ /** 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 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 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) 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. */ /** 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 FValueType 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) 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. */ /** 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 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 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) 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. */ /** 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 FValueType 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) 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. */ /** 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 FValueType FetchMul(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return FetchFn([InValue](FValueType Old) -> FValueType { 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) 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. */ /** 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 FValueType FetchDiv(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return FetchFn([InValue](FValueType Old) -> FValueType { 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) 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. */ /** 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 FValueType FetchMod(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](FValueType Old) -> FValueType { 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) 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. */ /** 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 FValueType FetchAnd(FValueType 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) 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. */ /** 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 FValueType FetchOr(FValueType 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) 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. */ /** 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 FValueType FetchXor(FValueType 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) 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. */ /** 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 FValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](FValueType Old) -> FValueType { 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) 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. */ /** 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 FValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](FValueType Old) -> FValueType { 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; }); } 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++() requires ((CIntegral<T> || CPointer<T>) ) { return ++NativeAtomic; }
FORCEINLINE ValueType operator++() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return ++NativeAtomic; }
/** Increments the atomic value by one. */ /** Increments the atomic value by one. */
FORCEINLINE ValueType operator++(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic++; } FORCEINLINE FValueType operator++() requires ((CIntegral<T> || CPointer<T>) ) { return ++NativeAtomic; }
FORCEINLINE ValueType operator++(int) volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { 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. */ /** Decrements the atomic value by one. */
FORCEINLINE ValueType operator--() requires ((CIntegral<T> || CPointer<T>) ) { return --NativeAtomic; } FORCEINLINE FValueType operator--() requires ((CIntegral<T> || CPointer<T>) ) { return --NativeAtomic; }
FORCEINLINE ValueType operator--() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return --NativeAtomic; } FORCEINLINE FValueType operator--() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return --NativeAtomic; }
/** Decrements the atomic value by one. */ /** Decrements the atomic value by one. */
FORCEINLINE ValueType operator--(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic--; } FORCEINLINE FValueType 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--(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; }
/** Adds with the atomic value. */ /** Adds with the atomic value. */
FORCEINLINE ValueType operator+=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic += InValue; } FORCEINLINE FValueType operator+=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic += InValue; }
FORCEINLINE ValueType operator+=(ptrdiff InValue) volatile requires (CPointer<T> && bIsAlwaysLockFree) { 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. */ /** Subtracts with the atomic value. */
FORCEINLINE ValueType operator-=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic -= InValue; } FORCEINLINE FValueType operator-=(FValueType 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) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
/** Subtracts with the atomic value. */ /** Subtracts with the atomic value. */
FORCEINLINE ValueType operator-=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic -= InValue; } FORCEINLINE FValueType 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) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
/** Multiples with the atomic value. */ /** Multiples with the atomic value. */
FORCEINLINE ValueType operator*=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchMul(InValue) * InValue; } FORCEINLINE FValueType operator*=(FValueType 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) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchMul(InValue) * InValue; }
/** Divides with the atomic value. */ /** Divides with the atomic value. */
FORCEINLINE ValueType operator/=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchDiv(InValue) / InValue; } FORCEINLINE FValueType operator/=(FValueType 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) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchDiv(InValue) / InValue; }
/** Models with the atomic value. */ /** Models with the atomic value. */
FORCEINLINE ValueType operator%=(ValueType InValue) requires (CIntegral<T> ) { return FetchMod(InValue) % InValue; } FORCEINLINE FValueType operator%=(FValueType 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) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchMod(InValue) % InValue; }
/** Performs bitwise AND with the atomic value. */ /** Performs bitwise AND with the atomic value. */
FORCEINLINE ValueType operator&=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic &= InValue; } FORCEINLINE FValueType operator&=(FValueType 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) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic &= InValue; }
/** Performs bitwise OR with the atomic value. */ /** Performs bitwise OR with the atomic value. */
FORCEINLINE ValueType operator|=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic |= InValue; } FORCEINLINE FValueType operator|=(FValueType 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) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic |= InValue; }
/** Performs bitwise XOR with the atomic value. */ /** Performs bitwise XOR with the atomic value. */
FORCEINLINE ValueType operator^=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic ^= InValue; } FORCEINLINE FValueType operator^=(FValueType 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) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic ^= InValue; }
/** Performs bitwise LSH with the atomic value. */ /** Performs bitwise LSH with the atomic value. */
FORCEINLINE ValueType operator<<=(size_t InValue) requires (CIntegral<T> ) { return FetchLsh(InValue) << InValue; } FORCEINLINE FValueType 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) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchLsh(InValue) << InValue; }
/** Performs bitwise RSH with the atomic value. */ /** Performs bitwise RSH with the atomic value. */
FORCEINLINE ValueType operator>>=(size_t InValue) requires (CIntegral<T> ) { return FetchRsh(InValue) >> InValue; } FORCEINLINE FValueType 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) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchRsh(InValue) >> InValue; }
protected: protected:
NativeAtomicType NativeAtomic; FNativeAtomic NativeAtomic;
}; };
@ -311,7 +311,7 @@ struct FAtomicFlag final : FSingleton
public: public:
/** Constructs an atomic flag. */ /** Constructs an atomic flag. */
FORCEINLINE constexpr FAtomicFlag() : NativeAtomic() { }; FORCEINLINE constexpr FAtomicFlag() = default;
/** Atomically sets flag to false. */ /** 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)); } 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. */ /** 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 { 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)); } 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. */ /** 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 { 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)); } 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. */ /** 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) { 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(); } 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: private:
NAMESPACE_STD::atomic_flag NativeAtomic; NAMESPACE_STD::atomic_flag NativeAtomic;

View File

@ -262,29 +262,29 @@ public:
{ {
Callable = InCallable; 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); 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 bIsTriviallyStorable = sizeof(FDecayedType) <= sizeof(InternalStorage) && alignof(FDecayedType) <= alignof(TFunctionStorage) && CTriviallyCopyable<FDecayedType>;
constexpr bool bIsSmallStorable = sizeof(DecayedType) <= sizeof(InternalStorage) && alignof(DecayedType) <= alignof(TFunctionStorage); constexpr bool bIsSmallStorable = sizeof(FDecayedType) <= sizeof(InternalStorage) && alignof(FDecayedType) <= alignof(TFunctionStorage);
if constexpr (bIsTriviallyStorable) if constexpr (bIsTriviallyStorable)
{ {
new (&InternalStorage) DecayedType(Forward<Ts>(Args)...); new (&InternalStorage) FDecayedType(Forward<Ts>(Args)...);
RTTI |= static_cast<uintptr>(ERepresentation::Trivial); RTTI |= static_cast<uintptr>(ERepresentation::Trivial);
} }
else if constexpr (bIsSmallStorable) else if constexpr (bIsSmallStorable)
{ {
new (&InternalStorage) DecayedType(Forward<Ts>(Args)...); new (&InternalStorage) FDecayedType(Forward<Ts>(Args)...);
RTTI |= static_cast<uintptr>(ERepresentation::Small); RTTI |= static_cast<uintptr>(ERepresentation::Small);
} }
else else
{ {
ExternalStorage = new DecayedType(Forward<Ts>(Args)...); ExternalStorage = new FDecayedType(Forward<Ts>(Args)...);
RTTI |= static_cast<uintptr>(ERepresentation::Big); 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 Ret, typename... Ts, typename F> struct TIsInvocableSignature<Ret(Ts...) const&&, F> : TBoolConstant<CInvocableResult<Ret, const F , Ts...>> { };
template <typename F> struct TFunctionInfo; 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 FFn = Ret(Ts...); using FCVRef = 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 FFn = Ret(Ts...); using FCVRef = 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 FFn = Ret(Ts...); using FCVRef = 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 FFn = Ret(Ts...); using FCVRef = 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 FFn = Ret(Ts...); using FCVRef = 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 FFn = Ret(Ts...); using FCVRef = const int&&; };
template <typename F, typename CVRef, bool bIsRef, bool bIsUnique = false> class TFunctionImpl; template <typename F, typename CVRef, bool bIsRef, bool bIsUnique = false> class TFunctionImpl;
@ -460,8 +460,8 @@ class TFunctionImpl<Ret(Ts...), CVRef, bIsRef, bIsUnique>
{ {
public: public:
using ResultType = Ret; using FResultType = Ret;
using ArgumentType = TTypeSequence<Ts...>; using FArgumentType = TTypeSequence<Ts...>;
FORCEINLINE constexpr TFunctionImpl() = default; FORCEINLINE constexpr TFunctionImpl() = default;
FORCEINLINE constexpr TFunctionImpl(const TFunctionImpl&) = default; FORCEINLINE constexpr TFunctionImpl(const TFunctionImpl&) = default;
@ -471,12 +471,12 @@ public:
FORCEINLINE constexpr ~TFunctionImpl() = default; FORCEINLINE constexpr ~TFunctionImpl() = default;
/** Invokes the stored callable function target with the parameters args. */ /** 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 FResultType 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 FResultType 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 FResultType 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 FResultType 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) 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) const&& requires (CSameAs<CVRef, const int&&>) { return CallImpl(Forward<Ts>(Args)...); }
/** @return false if instance stores a callable function target, true otherwise. */ /** @return false if instance stores a callable function target, true otherwise. */
NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& requires (!bIsRef) { return !IsValid(); } NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& requires (!bIsRef) { return !IsValid(); }
@ -487,14 +487,14 @@ public:
private: private:
using CallableType = ResultType(*)(uintptr, Ts&&...); using FCallableType = FResultType(*)(uintptr, Ts&&...);
TFunctionStorage<bIsRef, bIsUnique> Storage; 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!")); 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)...); return Callable(Storage.GetValuePtr(), Forward<Ts>(Args)...);
} }
@ -510,26 +510,26 @@ protected:
template <typename T, typename... Us> template <typename T, typename... Us>
FORCEINLINE constexpr TDecay<T>& Emplace(Us&&... Args) 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. // This add a l-value reference to a non-reference type, while preserving the r-value reference.
using ObjectType = TCopyCVRef<CVRef, DecayedType>; using FObjectType = TCopyCVRef<CVRef, FDecayedType>;
using InvokeType = TConditional<CReference<ObjectType>, ObjectType, ObjectType&>; using FInvokeType = TConditional<CReference<FObjectType>, FObjectType, FObjectType&>;
CallableType Callable = [](uintptr ObjectPtr, Ts&&... Args) -> ResultType FCallableType Callable = [](uintptr ObjectPtr, Ts&&... Args) -> FResultType
{ {
return InvokeResult<ResultType>( return InvokeResult<FResultType>(
static_cast<InvokeType>(*reinterpret_cast<DecayedType*>(ObjectPtr)), static_cast<FInvokeType>(*reinterpret_cast<FDecayedType*>(ObjectPtr)),
Forward<Ts>(Args)... Forward<Ts>(Args)...
); );
}; };
Storage.template Emplace<DecayedType>( Storage.template Emplace<FDecayedType>(
reinterpret_cast<uintptr>(Callable), reinterpret_cast<uintptr>(Callable),
Forward<Us>(Args)... 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); } 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> template <CFunction F>
class TFunctionRef final class TFunctionRef final
: public NAMESPACE_PRIVATE::TFunctionImpl< : public NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
true> true>
{ {
private: private:
using Impl = NAMESPACE_PRIVATE::TFunctionImpl< using FImpl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
true>; true>;
public: public:
@ -585,7 +585,7 @@ public:
FORCEINLINE constexpr TFunctionRef(T&& InValue) FORCEINLINE constexpr TFunctionRef(T&& InValue)
{ {
checkf(NAMESPACE_PRIVATE::FunctionIsBound(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef")); 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> template <typename T>
@ -602,21 +602,21 @@ public:
template <CFunction F> template <CFunction F>
class TFunction final class TFunction final
: public NAMESPACE_PRIVATE::TFunctionImpl< : public NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
false, false> false, false>
{ {
private: private:
using Impl = NAMESPACE_PRIVATE::TFunctionImpl< using FImpl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
false, false>; false, false>;
public: public:
/** Default constructor. */ /** 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(const TFunction&) = default;
FORCEINLINE TFunction(TFunction&&) = default; FORCEINLINE TFunction(TFunction&&) = default;
@ -634,8 +634,8 @@ public:
&& NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value) && NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value)
FORCEINLINE TFunction(T&& InValue) FORCEINLINE TFunction(T&& InValue)
{ {
if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Impl::Invalidate(); if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) FImpl::Invalidate();
else Impl::template Emplace<T>(Forward<T>(InValue)); else FImpl::template Emplace<T>(Forward<T>(InValue));
} }
/** /**
@ -647,7 +647,7 @@ public:
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>) && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE explicit TFunction(TInPlaceType<T>, Ts&&... Args) 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>>) && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE explicit TFunction(TInPlaceType<T>, initializer_list<U> IL, Ts&&... Args) 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. */ /** 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>>) && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE TDecay<T>& Emplace(Ts&&... Args) FORCEINLINE TDecay<T>& Emplace(Ts&&... Args)
{ {
Impl::Destroy(); FImpl::Destroy();
return Impl::template Emplace<T>(Forward<Ts>(Args)...); return FImpl::template Emplace<T>(Forward<Ts>(Args)...);
} }
/** /**
@ -710,15 +710,15 @@ public:
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>) && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE TDecay<T>& Emplace(initializer_list<U> IL, Ts&&... Args) FORCEINLINE TDecay<T>& Emplace(initializer_list<U> IL, Ts&&... Args)
{ {
Impl::Destroy(); FImpl::Destroy();
return Impl::template Emplace<T>(IL, Forward<Ts>(Args)...); return FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...);
} }
/** Removes any bound callable from the TFunction, restoring it to the default empty state. */ /** 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. */ /** 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> template <CFunction F>
class TUniqueFunction final class TUniqueFunction final
: public NAMESPACE_PRIVATE::TFunctionImpl< : public NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
false, true> false, true>
{ {
private: private:
using Impl = NAMESPACE_PRIVATE::TFunctionImpl< using FImpl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
false, true>; false, true>;
public: public:
/** Default constructor. */ /** 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(const TUniqueFunction&) = delete;
FORCEINLINE TUniqueFunction(TUniqueFunction&&) = default; FORCEINLINE TUniqueFunction(TUniqueFunction&&) = default;
@ -788,8 +788,8 @@ public:
&& NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value) && NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value)
FORCEINLINE TUniqueFunction(T&& InValue) FORCEINLINE TUniqueFunction(T&& InValue)
{ {
if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Impl::Invalidate(); if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) FImpl::Invalidate();
else Impl::template Emplace<T>(Forward<T>(InValue)); else FImpl::template Emplace<T>(Forward<T>(InValue));
} }
/** /**
@ -800,7 +800,7 @@ public:
&& CConstructibleFrom<TDecay<T>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>) && CConstructibleFrom<TDecay<T>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE explicit TUniqueFunction(TInPlaceType<T>, Ts&&... Args) 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>>) && CConstructibleFrom<TDecay<T>, initializer_list<U>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE explicit TUniqueFunction(TInPlaceType<T>, initializer_list<U> IL, Ts&&... Args) 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. */ /** 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 template <typename T> requires (NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value
&& !CTFunctionRef<TDecay<T>> && !CTFunction<TDecay<T>> && !CTUniqueFunction<TDecay<T>> && !CTFunctionRef<TDecay<T>> && !CTFunction<TDecay<T>> && !CTUniqueFunction<TDecay<T>>
@ -841,9 +841,9 @@ public:
&& CConstructibleFrom<TDecay<T>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>) && CConstructibleFrom<TDecay<T>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE TDecay<T>& Emplace(Ts&&... Args) FORCEINLINE TDecay<T>& Emplace(Ts&&... Args)
{ {
Impl::Destroy(); FImpl::Destroy();
using DecayedType = TDecay<T>;
return Impl::template Emplace<T>(Forward<Ts>(Args)...); 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>>) && CConstructibleFrom<TDecay<T>, initializer_list<U>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
FORCEINLINE TDecay<T>& Emplace(initializer_list<U> IL, Ts&&... Args) FORCEINLINE TDecay<T>& Emplace(initializer_list<U> IL, Ts&&... Args)
{ {
Impl::Destroy(); FImpl::Destroy();
using DecayedType = TDecay<T>;
return Impl::template Emplace<T>(IL, Forward<Ts>(Args)...); return FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...);
} }
/** Removes any bound callable from the TUniqueFunction, restoring it to the default empty state. */ /** 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. */ /** 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 NAMESPACE_PRIVATE_BEGIN
struct InvokeFunction struct FInvokeFunction
{ {
template <typename F, typename... Ts> template <typename F, typename... Ts>
static auto Invoke(F&& Object, Ts&&... Args) static auto Invoke(F&& Object, Ts&&... Args)
@ -20,7 +20,7 @@ struct InvokeFunction
} }
}; };
struct InvokeMemberFunction struct FInvokeMemberFunction
{ {
template <typename F, typename ObjectType, typename... Ts> template <typename F, typename ObjectType, typename... Ts>
static auto Invoke(F&& Func, ObjectType&& Object, Ts&&... Args) static auto Invoke(F&& Func, ObjectType&& Object, Ts&&... Args)
@ -37,7 +37,7 @@ struct InvokeMemberFunction
} }
}; };
struct InvokeMemberObject struct FInvokeMemberObject
{ {
template <typename F, typename ObjectType> template <typename F, typename ObjectType>
static auto Invoke(F&& Func, ObjectType&& Object) static auto Invoke(F&& Func, ObjectType&& Object)
@ -59,34 +59,34 @@ template <typename F,
typename Decayed = TDecay<F>, typename Decayed = TDecay<F>,
bool IsMemberFunction = CMemberFunctionPointer<Decayed>, bool IsMemberFunction = CMemberFunctionPointer<Decayed>,
bool IsMemberObject = CMemberObjectPointer<Decayed>> bool IsMemberObject = CMemberObjectPointer<Decayed>>
struct InvokeMember; struct FInvokeMember;
template <typename F, typename T, typename Decayed> 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> 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> 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> template <typename F, typename... Ts>
struct InvokeImpl; struct FInvokeImpl;
template <typename F> template <typename F>
struct InvokeImpl<F> : InvokeFunction { }; struct FInvokeImpl<F> : FInvokeFunction { };
template <typename F, typename T, typename... Ts> 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 NAMESPACE_PRIVATE_END
/** Invoke the Callable object f with the parameters args. */ /** Invoke the Callable object f with the parameters args. */
template <typename F, typename... Ts> requires (CInvocable<F, Ts...>) template <typename F, typename... Ts> requires (CInvocable<F, Ts...>)
FORCEINLINE constexpr auto Invoke(F&& Func, Ts&&... Args) 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. */ /** Invoke the Callable object f with the parameters args. */

View File

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

View File

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

View File

@ -24,7 +24,7 @@ template <typename T>
concept CTPropagateConst = NAMESPACE_PRIVATE::TIsTPropagateConst<TRemoveCV<T>>::Value; 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. * 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) template <typename T> requires (TPointerTraits<T>::bIsPointer)
@ -32,7 +32,7 @@ class TPropagateConst final
{ {
public: public:
using ElementType = TPointerTraits<T>::ElementType; using FElementType = TPointerTraits<T>::FElementType;
/** Constructs an TPropagateConst, default-initializing underlying pointer. */ /** Constructs an TPropagateConst, default-initializing underlying pointer. */
FORCEINLINE constexpr TPropagateConst() = default; FORCEINLINE constexpr TPropagateConst() = default;
@ -105,26 +105,26 @@ public:
NODISCARD FORCEINLINE constexpr decltype(auto) operator<=>(U InPtr) const& { return SynthThreeWayCompare(Ptr, InPtr); } 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. */ /** @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 FElementType* Get() { return TPointerTraits<T>::ToAddress(Ptr); }
NODISCARD FORCEINLINE constexpr const ElementType* Get() const { 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. */ /** @return true if *this owns an object, false otherwise. */
NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; } NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; }
NODISCARD FORCEINLINE constexpr explicit operator bool() 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(). */ /** @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 FElementType& 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 const FElementType& 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 FElementType* 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 const FElementType* operator->() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); }
/** @return The element at index, i.e. Get()[Index]. */ /** @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 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]; } 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. */ /** @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 FElementType*() requires (CConvertibleTo<T, FElementType*>) { return Ptr; }
NODISCARD FORCEINLINE constexpr operator const ElementType*() const requires (CConvertibleTo<T, ElementType*>) { return Ptr; } NODISCARD FORCEINLINE constexpr operator const FElementType*() const requires (CConvertibleTo<T, FElementType*>) { return Ptr; }
/** @return The reference to the pointer-like object stored. */ /** @return The reference to the pointer-like object stored. */
NODISCARD FORCEINLINE constexpr T& GetUnderlying() { return Ptr; } NODISCARD FORCEINLINE constexpr T& GetUnderlying() { return Ptr; }

View File

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

View File

@ -49,7 +49,7 @@ struct TTupleElementImpl;
template <size_t I, typename... Ts> template <size_t I, typename... Ts>
struct TTupleElementImpl<I, TTuple<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> template <bool bTrue, typename... Ts>
@ -77,12 +77,12 @@ struct TTupleBasicElement
{ {
private: private:
using ValueType = T; using FValueType = T;
ValueType Value; FValueType Value;
public: public:
template <typename Type> template <typename Type> requires (CConstructibleFrom<T, Type&&>)
FORCEINLINE constexpr TTupleBasicElement(Type&& Arg) FORCEINLINE constexpr TTupleBasicElement(Type&& Arg)
: Value(Forward<Type>(Arg)) : Value(Forward<Type>(Arg))
{ } { }
@ -110,10 +110,10 @@ public:
template <typename T> \ template <typename T> \
struct TTupleBasicElement<T, Index> \ struct TTupleBasicElement<T, Index> \
{ \ { \
using Name##Type = T; \ using F##Name##Type = T; \
Name##Type Name; \ F##Name##Type Name; \
\ \
template <typename Type> \ template <typename Type> requires (CConstructibleFrom<T, F##Name##Type&&>) \
FORCEINLINE constexpr TTupleBasicElement(Type&& Arg) \ FORCEINLINE constexpr TTupleBasicElement(Type&& Arg) \
: Name(Forward<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; inline constexpr size_t TTupleIndex = NAMESPACE_PRIVATE::TTupleIndexImpl<T, TRemoveCV<U>>::Value;
template <size_t I, CTTuple U> 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> template <typename... Ts>
class TTuple final : public NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...> class TTuple final : public NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>
{ {
private: private:
using Super = NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>; using FSuper = NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>;
using Helper = NAMESPACE_PRIVATE::TTupleHelper<TIndexSequenceFor<Ts...>>; using FHelper = NAMESPACE_PRIVATE::TTupleHelper<TIndexSequenceFor<Ts...>>;
public: public:
@ -334,7 +334,7 @@ public:
template <typename... Us> requires (sizeof...(Ts) >= 1 && sizeof...(Us) == sizeof...(Ts)) template <typename... Us> requires (sizeof...(Ts) >= 1 && sizeof...(Us) == sizeof...(Ts))
&& (true && ... && CConstructibleFrom<Ts, Us&&>) && (true && ... && CConstructibleFrom<Ts, Us&&>)
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(Us&&... Args) 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. */ /** 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&>) && (true && ... && CConstructibleFrom<Ts, const Us&>)
&& NAMESPACE_PRIVATE::TTupleConvertCopy<sizeof...(Ts) != 1, Ts..., Us...>::Value) && NAMESPACE_PRIVATE::TTupleConvertCopy<sizeof...(Ts) != 1, Ts..., Us...>::Value)
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(const TTuple<Us...>& InValue) 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. */ /** Converting move constructor. Initializes each element of the tuple with the corresponding element of other. */
@ -350,7 +350,7 @@ public:
&& (true && ... && CConstructibleFrom<Ts, Us&&>) && (true && ... && CConstructibleFrom<Ts, Us&&>)
&& NAMESPACE_PRIVATE::TTupleConvertMove<sizeof...(Ts) != 1, Ts..., Us...>::Value) && NAMESPACE_PRIVATE::TTupleConvertMove<sizeof...(Ts) != 1, Ts..., Us...>::Value)
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(TTuple<Us...>&& InValue) 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. */ /** Copies/moves content of other into a new instance. */
@ -362,7 +362,7 @@ public:
&& (true && ... && CAssignableFrom<Ts&, const Us&>)) && (true && ... && CAssignableFrom<Ts&, const Us&>))
FORCEINLINE constexpr TTuple& operator=(const TTuple<Us...>& InValue) FORCEINLINE constexpr TTuple& operator=(const TTuple<Us...>& InValue)
{ {
Helper::Assign(*this, InValue); FHelper::Assign(*this, InValue);
return *this; return *this;
} }
@ -371,7 +371,7 @@ public:
&& (true && ... && CAssignableFrom<Ts&, Us&&>)) && (true && ... && CAssignableFrom<Ts&, Us&&>))
FORCEINLINE constexpr TTuple& operator=(TTuple<Us...>&& InValue) FORCEINLINE constexpr TTuple& operator=(TTuple<Us...>&& InValue)
{ {
Helper::Assign(*this, MoveTemp(InValue)); FHelper::Assign(*this, MoveTemp(InValue));
return *this; return *this;
} }
@ -396,8 +396,8 @@ public:
template <typename... Us> requires (sizeof...(Ts) == sizeof...(Us) && NAMESPACE_PRIVATE::CTTupleSynthThreeWayComparable<TTypeSequence<Ts...>, TTypeSequence<Us...>>) 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) NODISCARD friend FORCEINLINE constexpr TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...> operator<=>(const TTuple& LHS, const TTuple<Us...>& RHS)
{ {
using R = TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...>; using FResult = TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...>;
return NAMESPACE_PRIVATE::TTupleThreeWay<R, TMakeIndexSequence<sizeof...(Ts)>>::Do(LHS, RHS); 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)). */ /** 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>>(); } 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. */ /** 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) & { 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 Helper::Apply(Forward<F>(Func), static_cast<const 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 Helper::Apply(Forward<F>(Func), static_cast< volatile 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 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) 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 Helper::Apply(Forward<F>(Func), static_cast< 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 Helper::Apply(Forward<F>(Func), static_cast<const 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 Helper::Apply(Forward<F>(Func), static_cast< volatile 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 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) 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. */ /** 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)); } 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); } 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. */ /** 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) & { 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 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) 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 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) 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 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) 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 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) && { 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 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) 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 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) 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 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) 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. */ /** 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() & { return FHelper::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() 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 Helper::template Construct<T>(static_cast< volatile 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 Helper::template Construct<T>(static_cast<const 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 Helper::template Construct<T>(static_cast< 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 Helper::template Construct<T>(static_cast<const 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 Helper::template Construct<T>(static_cast< volatile 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 Helper::template Construct<T>(static_cast<const 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. */ /** @return The number of elements in the tuple. */
NODISCARD static FORCEINLINE constexpr size_t Num() { return sizeof...(Ts); } NODISCARD static FORCEINLINE constexpr size_t Num() { return sizeof...(Ts); }
@ -555,13 +555,13 @@ struct TTupleCatResultImpl;
template <typename... Ts, typename... TTupleTypes> template <typename... Ts, typename... TTupleTypes>
struct TTupleCatResultImpl<TTuple<Ts...>, TTupleTypes...> struct TTupleCatResultImpl<TTuple<Ts...>, TTupleTypes...>
{ {
using Type = typename TTupleCatResultImpl<TTupleTypes..., Ts...>::Type; using FType = typename TTupleCatResultImpl<TTupleTypes..., Ts...>::FType;
}; };
template <typename... Ts> template <typename... Ts>
struct TTupleCatResultImpl<FTupleEndFlag, Ts...> struct TTupleCatResultImpl<FTupleEndFlag, Ts...>
{ {
using Type = TTuple<Ts...>; using FType = TTuple<Ts...>;
}; };
template <typename R, typename Indices> template <typename R, typename Indices>
@ -571,14 +571,14 @@ template <typename... RTypes, size_t... Indices>
struct TTupleCatMake<TTuple<RTypes...>, TIndexSequence<Indices...>> struct TTupleCatMake<TTuple<RTypes...>, TIndexSequence<Indices...>>
{ {
template <typename T, typename U> 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> template <typename TTupleType>
FORCEINLINE static constexpr TTuple<RTypes...> Do(TTupleType&& InValue) FORCEINLINE static constexpr TTuple<RTypes...> Do(TTupleType&& InValue)
{ {
return TTuple<RTypes...> 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>() Forward<TTupleType>(InValue).template GetValue<Indices>()
)... )...
@ -642,15 +642,15 @@ struct TTupleVisitImpl<TIndexSequence<>>
NAMESPACE_PRIVATE_END NAMESPACE_PRIVATE_END
template <typename... TTupleTypes> requires (true && ... && CTTuple<TRemoveCVRef<TTupleTypes>>) 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. */ /** Creates a tuple by concatenating any number of tuples. */
template <typename... TTupleTypes> requires (true && ... && CTTuple<TRemoveCVRef<TTupleTypes>>) template <typename... TTupleTypes> requires (true && ... && CTTuple<TRemoveCVRef<TTupleTypes>>)
FORCEINLINE constexpr decltype(auto) TupleCat(TTupleTypes&&... Args) FORCEINLINE constexpr decltype(auto) TupleCat(TTupleTypes&&... Args)
{ {
using R = TTupleCatResult<TTupleTypes...>; using FResult = TTupleCatResult<TTupleTypes...>;
if constexpr (sizeof...(Args) == 0) return R(); if constexpr (sizeof...(Args) == 0) return FResult();
else return NAMESPACE_PRIVATE::TTupleCatImpl<R>::Do(Forward<TTupleTypes>(Args)...); 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>...>; }) template <typename... Ts, typename... Us> requires (requires { typename TTuple<TCommonType<Ts, Us>...>; })
struct TBasicCommonType<TTuple<Ts...>, TTuple<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> template <typename... Ts, typename... Us, template<typename> typename TQualifiers, template<typename> typename UQualifiers>
requires (requires { typename TTuple<TCommonReference<TQualifiers<Ts>, UQualifiers<Us>>...>; }) requires (requires { typename TTuple<TCommonReference<TQualifiers<Ts>, UQualifiers<Us>>...>; })
struct TBasicCommonReference<TTuple<Ts...>, TTuple<Us...>, TQualifiers, UQualifiers> 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(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END NAMESPACE_REDCRAFT_END
// ReSharper disable CppInconsistentNaming
NAMESPACE_STD_BEGIN NAMESPACE_STD_BEGIN
// Support structure binding, should not be directly used. // 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(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END NAMESPACE_REDCRAFT_END
// ReSharper restore CppInconsistentNaming

View File

@ -24,8 +24,8 @@ void AsConst(const T&& Ref) = delete;
template <typename T> template <typename T>
FORCEINLINE constexpr TRemoveReference<T>&& MoveTemp(T&& Obj) FORCEINLINE constexpr TRemoveReference<T>&& MoveTemp(T&& Obj)
{ {
using CastType = TRemoveReference<T>; using FCastType = TRemoveReference<T>;
return static_cast<CastType&&>(Obj); return static_cast<FCastType&&>(Obj);
} }
/** CopyTemp will enforce the creation of an rvalue which can bind to rvalue reference parameters. */ /** 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> template <size_t I, typename... Ts>
struct TVariantAlternativeImpl<I, TVariant<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> template <typename T, typename TSequence>
struct TVariantOverloadType struct TVariantOverloadType
{ {
using FrontType = Meta::TFront<TSequence>; using FFrontType = Meta::TFront<TSequence>;
using NextSequence = Meta::TPop<TSequence>; using FNextSequence = Meta::TPop<TSequence>;
using NextUniqueSequence = typename TVariantOverloadType<T, NextSequence>::Type; using FNextUniqueSequence = typename TVariantOverloadType<T, FNextSequence>::FType;
// T_i x[] = { Forward<T>(t) }; // 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> template <typename T>
struct TVariantOverloadType<T, TTypeSequence<>> struct TVariantOverloadType<T, TTypeSequence<>>
{ {
using Type = TTypeSequence<>; using FType = TTypeSequence<>;
}; };
template <typename T, typename... Ts> 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 NAMESPACE_PRIVATE_END
@ -77,7 +77,7 @@ template <typename T, CTVariant U>
inline constexpr size_t TVariantIndex = NAMESPACE_PRIVATE::TVariantIndexImpl<T, TRemoveCV<U>>::Value; inline constexpr size_t TVariantIndex = NAMESPACE_PRIVATE::TVariantIndexImpl<T, TRemoveCV<U>>::Value;
template <size_t I, CTVariant U> 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 * 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); if (IsValid()) MoveConstructImpl[InValue.GetIndex()](&Value, &InValue.Value);
} }
/** /**
* Converting constructor. Constructs a variant holding the alternative type that would be selected * 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 * 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>>) && !CSameAs<TVariant, TRemoveCVRef<T>>)
FORCEINLINE constexpr TVariant(T&& InValue) : TVariant(InPlaceType<NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>>, Forward<T>(InValue)) 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).... */ /** 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...>) template <typename T, typename... Us> requires (CConstructibleFrom<T, Us...>)
FORCEINLINE constexpr explicit TVariant(TInPlaceType<T>, Us&&... Args) FORCEINLINE constexpr explicit TVariant(TInPlaceType<T>, Us&&... Args)
@ -139,10 +139,10 @@ public:
FORCEINLINE constexpr explicit TVariant(TInPlaceIndex<I>, Us&&... Args) FORCEINLINE constexpr explicit TVariant(TInPlaceIndex<I>, Us&&... Args)
: TypeIndex(I) : TypeIndex(I)
{ {
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>; using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
new (&Value) SelectedType(Forward<Us>(Args)...); 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).... */ /** 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...>) 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) 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) FORCEINLINE constexpr explicit TVariant(TInPlaceIndex<I>, initializer_list<T> IL, Us&&... Args)
: TypeIndex(I) : TypeIndex(I)
{ {
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>; using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
new (&Value) SelectedType(IL, Forward<Us>(Args)...); new (&Value) FSelectedType(IL, Forward<Us>(Args)...);
} }
/** Destroys the contained object, if any, as if by a call to Reset(). */ /** 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); if (GetIndex() == InValue.GetIndex()) CopyAssignImpl[InValue.GetIndex()](&Value, &InValue.Value);
else else
{ {
Reset(); Reset();
CopyConstructImpl[InValue.GetIndex()](&Value, &InValue.Value); CopyConstructImpl[InValue.GetIndex()](&Value, &InValue.Value);
TypeIndex = static_cast<uint8>(InValue.GetIndex()); TypeIndex = static_cast<uint8>(InValue.GetIndex());
@ -224,14 +224,14 @@ public:
template <typename T> requires (requires { typename NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>; }) template <typename T> requires (requires { typename NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>; })
FORCEINLINE constexpr TVariant& operator=(T&& InValue) 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 else
{ {
Reset(); Reset();
new (&Value) SelectedType(Forward<T>(InValue)); new (&Value) FSelectedType(Forward<T>(InValue));
TypeIndex = TVariantIndex<SelectedType, TVariant<Ts...>>; TypeIndex = TVariantIndex<FSelectedType, TVariant<Ts...>>;
} }
return *this; return *this;
@ -277,7 +277,7 @@ public:
/** @return true if instance does not contain a value, otherwise false. */ /** @return true if instance does not contain a value, otherwise false. */
NODISCARD FORCEINLINE constexpr bool operator==(FInvalid) const& { return !IsValid(); } 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.... */ /** 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...>) template <typename T, typename... Us> requires (CConstructibleFrom<T, Us...>)
FORCEINLINE constexpr T& Emplace(Us&&... Args) 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).... * 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. * @param Args - The arguments to be passed to the constructor of the contained object.
* *
* @return A reference to the new contained object. * @return A reference to the new contained object.
*/ */
template <size_t I, typename... Us> requires (I < sizeof...(Ts) template <size_t I, typename... Us> requires (I < sizeof...(Ts)
@ -299,13 +299,13 @@ public:
{ {
Reset(); Reset();
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>; using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
SelectedType* Result = new (&Value) SelectedType(Forward<Us>(Args)...); FSelectedType* Result = new (&Value) FSelectedType(Forward<Us>(Args)...);
TypeIndex = I; TypeIndex = I;
return *Result; return *Result;
} }
/** Equivalent to Emplace<I>(IL, Forward<Us>(Args)...), where I is the zero-based index of T in Types.... */ /** 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...>) template <typename T, typename U, typename... Us> requires (CConstructibleFrom<T, initializer_list<U>, Us...>)
FORCEINLINE constexpr T& Emplace(initializer_list<U> IL, Us&&... Args) 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).... * 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. * @param IL, Args - The arguments to be passed to the constructor of the contained object.
* *
* @return A reference to the new contained object. * @return A reference to the new contained object.
*/ */
template <size_t I, typename T, typename... Us> requires (I < sizeof...(Ts) template <size_t I, typename T, typename... Us> requires (I < sizeof...(Ts)
@ -327,8 +327,8 @@ public:
{ {
Reset(); Reset();
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>; using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
SelectedType* Result = new (&Value) SelectedType(IL, Forward<Us>(Args)...); FSelectedType* Result = new (&Value) FSelectedType(IL, Forward<Us>(Args)...);
TypeIndex = I; TypeIndex = I;
return *Result; return *Result;
@ -423,7 +423,7 @@ public:
} }
private: private:
static constexpr const type_info* TypeInfos[] = { &typeid(Ts)... }; static constexpr const type_info* TypeInfos[] = { &typeid(Ts)... };
using FCopyConstructImpl = void(*)(void*, const void*); using FCopyConstructImpl = void(*)(void*, const void*);
@ -448,7 +448,7 @@ NAMESPACE_PRIVATE_BEGIN
template <typename F, typename... VariantTypes> template <typename F, typename... VariantTypes>
struct TVariantVisitImpl struct TVariantVisitImpl
{ {
struct GetTotalNum struct FGetTotalNum
{ {
FORCEINLINE static constexpr size_t Do() FORCEINLINE static constexpr size_t Do()
{ {
@ -464,10 +464,10 @@ struct TVariantVisitImpl
} }
return Result; return Result;
}; }
}; };
struct EncodeIndices struct FEncodeIndices
{ {
FORCEINLINE static constexpr size_t Do(initializer_list<size_t> Indices) FORCEINLINE static constexpr size_t Do(initializer_list<size_t> Indices)
{ {
@ -482,10 +482,10 @@ struct TVariantVisitImpl
} }
return Result; return Result;
}; }
}; };
struct DecodeExtent struct FDecodeExtent
{ {
FORCEINLINE static constexpr size_t Do(size_t EncodedIndex, size_t Extent) FORCEINLINE static constexpr size_t Do(size_t EncodedIndex, size_t Extent)
{ {
@ -497,76 +497,76 @@ struct TVariantVisitImpl
} }
return EncodedIndex % VariantNums[Extent]; return EncodedIndex % VariantNums[Extent];
}; }
}; };
template <size_t EncodedIndex, typename> template <size_t EncodedIndex, typename>
struct InvokeEncoded; struct FInvokeEncoded;
template <size_t EncodedIndex, size_t... ExtentIndices> 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) 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> template <typename Ret>
struct Result struct FResult
{ {
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants) 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> template <typename>
struct InvokeVariant; struct FInvokeVariant;
template <size_t... EncodedIndices> template <size_t... EncodedIndices>
struct InvokeVariant<TIndexSequence<EncodedIndices...>> struct FInvokeVariant<TIndexSequence<EncodedIndices...>>
{ {
FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants) 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 FResultType = TCommonType<decltype(FInvokeEncoded<EncodedIndices, FExtentIndices>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...))...>;
using InvokeImplType = ResultType(*)(F&&, VariantTypes&&...);
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> template <typename Ret>
struct Result struct FResult
{ {
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants) 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) 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> template <typename Ret>
struct Result struct FResult
{ {
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants) 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) 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().")); 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) NAMESPACE_MODULE_END(Utility)

View File

@ -20,58 +20,58 @@ template <typename T, typename U, template <typename> typename TQualifiers, temp
NAMESPACE_PRIVATE_BEGIN NAMESPACE_PRIVATE_BEGIN
// Template class declaration for the common Type implementation // Template class declaration for the common type implementation
template <typename...> template <typename...>
struct TCommonTypeImpl; struct TCommonTypeImpl;
// If sizeof...(Ts) is zero, there is no member Type // If sizeof...(Ts) is zero, there is no member FType
template <> template <>
struct TCommonTypeImpl<> { }; 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> template <typename T>
struct TCommonTypeImpl<T> : TCommonTypeImpl<T, T> { }; struct TCommonTypeImpl<T> : TCommonTypeImpl<T, T> { };
// If sizeof...(Ts) is two // 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> concept CDecayed = CSameAs<T, TDecay<T>> && CSameAs<U, TDecay<U>>;
template <typename T, typename U> requires (!CDecayed<T, U>) template <typename T, typename U> requires (!CDecayed<T, U>)
struct TCommonTypeImpl<T, U> : TCommonTypeImpl<TDecay<T>, TDecay<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 // 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>::Type; }; 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>) template <typename T, typename U> requires (CDecayed<T, U> && CBasicCommonType<T, U>)
struct TCommonTypeImpl<T, U> : TBasicCommonType<T, U> struct TCommonTypeImpl<T, U> : TBasicCommonType<T, U>
{ {
// If such a specialization has a member named type, // 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 // 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 // Additionally, TBasicCommonType<T, U>::FType and TBasicCommonType<U, T>::FType 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(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>::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(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>::Type, typename TBasicCommonType<U, T>::Type>, "TBasicCommonType<T, U>::Type and TBasicCommonType<U, T>::Type must denote the same type"); 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> 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>) 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, // 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 // 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> 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>) 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 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 // 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>::Type; }) 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>::Type, W, Ts...> { }; 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...> template <typename...>
struct TCommonTypeImpl { }; struct TCommonTypeImpl { };
@ -83,7 +83,7 @@ NAMESPACE_PRIVATE_BEGIN
template <typename...> template <typename...>
struct TCommonReferenceImpl; 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> template <typename, typename>
struct TSimpleCommonReferenceImpl; struct TSimpleCommonReferenceImpl;
@ -91,89 +91,89 @@ struct TSimpleCommonReferenceImpl;
template <typename> template <typename>
struct TQualifiersImpl; struct TQualifiersImpl;
// If sizeof...(T) is zero, there is no member Type // If sizeof...(T) is zero, there is no member FType
template <> template <>
struct TCommonReferenceImpl<> { }; 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> template <typename T>
struct TCommonReferenceImpl<T> { using Type = T; }; struct TCommonReferenceImpl<T> { using FType = T; };
// If sizeof...(Ts) is two // 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 // 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>::Type; }; template <typename T, typename U> concept CSimpleCommonReference = requires { typename TSimpleCommonReferenceImpl<T, U>::FType; };
template <typename T, typename U> requires (CSimpleCommonReference<T, U>) template <typename T, typename U> requires (CSimpleCommonReference<T, U>)
struct TCommonReferenceImpl<T, U> : TSimpleCommonReferenceImpl<T, U> { }; struct TCommonReferenceImpl<T, U> : TSimpleCommonReferenceImpl<T, U> { };
// Otherwise, if TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQ, UQ>::Type exists // 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 Apply, TQualifiersImpl<U>::template Apply> { }; 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>::Type; }; 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>) template <typename T, typename U> requires (!CSimpleCommonReference<T, U> && CBasicCommonReference<T, U>)
struct TCommonReferenceImpl<T, U> : TBasicCommonReferenceImpl<T, U> struct TCommonReferenceImpl<T, U> : TBasicCommonReferenceImpl<T, U>
{ {
// If such a specialization has a member named type, // 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 // 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 // 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>::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(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>::Type, typename TBasicCommonReferenceImpl<U, T>::Type>, "TBasicCommonReference<T, U, TQualifiers, UQualifiers>::Type and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::Type must denote the same type"); 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 // 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 Apply = TCopyCV<T, U>; }; template <typename T> struct TQualifiersImpl { template <typename U> using FApply = 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 FApply = TAddLValueReference<TCopyCV<T, U>>; };
template <typename T> struct TQualifiersImpl<T&&> { template <typename U> using Apply = TAddRValueReference<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> T Val();
template <typename T, typename U> concept CConditionalValType = requires { typename TVoid<decltype(false ? Val<T>() : Val<U>())>; }; 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>) 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> 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>) 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> { }; 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 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 // 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>::Type; }) 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>::Type, W, Ts...> { }; 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...> template <typename...>
struct TCommonReferenceImpl { }; struct TCommonReferenceImpl { };
// If T is CV1 X & and U is CV2 Y & (i.e., both are lvalue reference types): // 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 &>()), // 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 // 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>&>())>) 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 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 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 // 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> &&>) 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 Type = TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::Type> &&; }; 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 && // 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 // 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 // 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>) template <typename T, typename U> requires (CConvertibleTo<U&&, typename TSimpleCommonReferenceImpl<T&, const U&>::FType>)
struct TSimpleCommonReferenceImpl<T&, U&&> { using Type = typename TSimpleCommonReferenceImpl<T&, const U&>::Type; }; 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 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> template <typename T, typename U>
struct TSimpleCommonReferenceImpl { }; struct TSimpleCommonReferenceImpl { };
NAMESPACE_PRIVATE_END NAMESPACE_PRIVATE_END
template <typename... Ts> using TCommonType = typename NAMESPACE_PRIVATE::TCommonTypeImpl<Ts...>::Type; template <typename... Ts> using TCommonType = typename NAMESPACE_PRIVATE::TCommonTypeImpl<Ts...>::FType;
template <typename... Ts> using TCommonReference = typename NAMESPACE_PRIVATE::TCommonReferenceImpl<Ts...>::Type; template <typename... Ts> using TCommonReference = typename NAMESPACE_PRIVATE::TCommonReferenceImpl<Ts...>::FType;
template <typename... Ts> template <typename... Ts>
concept CCommonReference = concept CCommonReference =

View File

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

View File

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