Compare commits

..

No commits in common. "312cfe40979bbd820cb17344ce61981bd16f1723" and "d88eb4be5ec1c2026f4fc39370bb5a0ebdcb43ca" have entirely different histories.

57 changed files with 1705 additions and 1877 deletions

View File

@ -46,7 +46,7 @@ public:
}; };
FMemoryLeakChecker GMemoryLeakChecker; FMemoryLeakChecker MemoryLeakChecker;
#endif #endif
@ -80,7 +80,7 @@ void* Malloc(size_t Count, size_t Alignment)
check(Result != nullptr); check(Result != nullptr);
check_code({ GMemoryLeakChecker.AddMemoryAllocationCount(); }); check_code({ MemoryLeakChecker.AddMemoryAllocationCount(); });
return Result; return Result;
} }
@ -139,7 +139,7 @@ void Free(void* Ptr)
} }
# endif # endif
check_code({ GMemoryLeakChecker.ReleaseMemoryAllocationCount(); }); check_code({ MemoryLeakChecker.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> GRandState = 586103306; TAtomic<uint32> RandState = 586103306;
NAMESPACE_UNNAMED_END NAMESPACE_UNNAMED_END
uint32 Seed(uint32 InSeed) uint32 Seed(uint32 InSeed)
{ {
uint32 OldSeed = GRandState.Load(EMemoryOrder::Relaxed); uint32 OldSeed = RandState.Load(EMemoryOrder::Relaxed);
if (InSeed != 0) GRandState.Store(InSeed, EMemoryOrder::Relaxed); if (InSeed != 0) RandState.Store(InSeed, EMemoryOrder::Relaxed);
return OldSeed; return OldSeed;
} }
@ -27,7 +27,7 @@ uint32 Rand()
{ {
uint32 Result; uint32 Result;
GRandState.FetchFn( RandState.FetchFn(
[&Result](uint32 Value) [&Result](uint32 Value)
{ {
Result = Value; Result = Value;

View File

@ -7,8 +7,6 @@ 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()
@ -605,8 +603,6 @@ 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*>::FPointerType, int64*>)); always_check((CSameAs<TPointerTraits<int64*>::PointerType, int64*>));
always_check((CSameAs<TPointerTraits<int64*>::FElementType, int64>)); always_check((CSameAs<TPointerTraits<int64*>::ElementType, 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(*)[]>::FPointerType, int64(*)[]>)); always_check((CSameAs<TPointerTraits<int64(*)[]>::PointerType, int64(*)[]>));
always_check((CSameAs<TPointerTraits<int64(*)[]>::FElementType, int64>)); always_check((CSameAs<TPointerTraits<int64(*)[]>::ElementType, 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>>::FPointerType, TSharedPtr<int64>>)); always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::PointerType, TSharedPtr<int64>>));
always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::FElementType, int64>)); always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::ElementType, 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[]>>::FPointerType, TSharedPtr<int64[]>>)); always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::PointerType, TSharedPtr<int64[]>>));
always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::FElementType, int64>)); always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::ElementType, 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(*FFuncType)(int32, int32, int32); typedef int32(*FuncType)(int32, int32, int32);
FFuncType TempA = [](int32 A, int32 B, int32 C) -> int32 { return A * B * C; }; FuncType TempA = [](int32 A, int32 B, int32 C) -> int32 { return A * B * C; };
TReferenceWrapper<FFuncType> TempB(TempA); TReferenceWrapper<FuncType> 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,15 +330,14 @@ void TestVariant()
} }
{ {
using FVariantType = TVariant<int32, int64, float64>; using VariantType = TVariant<int32, int64, float64>;
FVariantType TempArray[] = { 10, 15ll, 1.5 }; VariantType 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);
@ -348,12 +347,11 @@ void TestVariant()
TempA TempA
); );
FVariantType TempB = Visit([](auto&& A) -> FVariantType { return A + A; }, TempA); VariantType TempB = Visit([](auto&& A) -> VariantType { 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);
@ -368,7 +366,6 @@ 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);
@ -420,7 +417,6 @@ 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);
@ -433,8 +429,6 @@ 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)>));
@ -494,8 +488,6 @@ 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
} }
{ {
@ -877,11 +869,11 @@ void TestTuple()
// always_check((CSameAs<TTupleElement<4, TTuple<double, float&, char&&>>, double>)); // always_check((CSameAs<TTupleElement<4, TTuple<double, float&, char&&>>, double>));
{ {
using FType = TTuple<int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64, using Type = 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>;
FType Temp; Type Temp;
Temp.First = 0; Temp.First = 0;
Temp.Second = 0; Temp.Second = 0;
@ -900,20 +892,20 @@ void TestTuple()
Temp.Fifteenth = 0; Temp.Fifteenth = 0;
Temp.Sixteenth = 0; Temp.Sixteenth = 0;
always_check(CDefaultConstructible<FType>); always_check(CDefaultConstructible<Type>);
always_check(CTriviallyDefaultConstructible<FType>); always_check(CTriviallyDefaultConstructible<Type>);
always_check(CConstructibleFrom<FType>); always_check(CConstructibleFrom<Type>);
always_check(CTriviallyConstructibleFrom<FType>); always_check(CTriviallyConstructibleFrom<Type>);
always_check(CCopyConstructible<FType>); always_check(CCopyConstructible<Type>);
always_check(CTriviallyCopyConstructible<FType>); always_check(CTriviallyCopyConstructible<Type>);
always_check(CMoveConstructible<FType>); always_check(CMoveConstructible<Type>);
always_check(CTriviallyMoveConstructible<FType>); always_check(CTriviallyMoveConstructible<Type>);
always_check(CCopyAssignable<FType>); always_check(CCopyAssignable<Type>);
always_check(CTriviallyCopyAssignable<FType>); always_check(CTriviallyCopyAssignable<Type>);
always_check(CMoveAssignable<FType>); always_check(CMoveAssignable<Type>);
always_check(CTriviallyMoveAssignable<FType>); always_check(CTriviallyMoveAssignable<Type>);
always_check(CDestructible<FType>); always_check(CDestructible<Type>);
always_check(CTriviallyDestructible<FType>); always_check(CTriviallyDestructible<Type>);
} }
{ {
@ -1092,25 +1084,25 @@ struct FFunctionDebug
void Print(int32 In) { Output[Index++] = In; } void Print(int32 In) { Output[Index++] = In; }
}; };
FFunctionDebug GFunctionDebug; FFunctionDebug FunctionDebug;
struct FPrintAdd struct FPrintAdd
{ {
FPrintAdd(int32 InNum) : Num(InNum) { } FPrintAdd(int32 InNum) : Num(InNum) { }
void F(int32 I) const { GFunctionDebug.Print(Num + I); } void F(int32 I) const { FunctionDebug.Print(Num + I); }
int32 Num; int32 Num;
}; };
void PrintNum(int32 I) void PrintNum(int32 I)
{ {
GFunctionDebug.Print(I); FunctionDebug.Print(I);
} }
struct FPrintNum struct FPrintNum
{ {
void operator()(int32 I) const void operator()(int32 I) const
{ {
GFunctionDebug.Print(I); FunctionDebug.Print(I);
} }
}; };
@ -1318,7 +1310,7 @@ void TestFunction()
AddDisplay(314159, 1); AddDisplay(314159, 1);
TFunction<int32(FPrintAdd const&)> Num = &FPrintAdd::Num; TFunction<int32(FPrintAdd const&)> Num = &FPrintAdd::Num;
GFunctionDebug.Print(Num(Foo)); FunctionDebug.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);
@ -1334,21 +1326,21 @@ void TestFunction()
return Fac(N); return Fac(N);
}; };
for (int32 I = 5; I < 8; ++I) GFunctionDebug.Print(Factorial(I)); for (int32 I = 5; I < 8; ++I) FunctionDebug.Print(Factorial(I));
always_check(GFunctionDebug.Index == 12); always_check(FunctionDebug.Index == 12);
always_check(GFunctionDebug.Output[0] == -9); always_check(FunctionDebug.Output[0] == -9);
always_check(GFunctionDebug.Output[1] == 42); always_check(FunctionDebug.Output[1] == 42);
always_check(GFunctionDebug.Output[2] == 31337); always_check(FunctionDebug.Output[2] == 31337);
always_check(GFunctionDebug.Output[3] == 314160); always_check(FunctionDebug.Output[3] == 314160);
always_check(GFunctionDebug.Output[4] == 314160); always_check(FunctionDebug.Output[4] == 314160);
always_check(GFunctionDebug.Output[5] == 314159); always_check(FunctionDebug.Output[5] == 314159);
always_check(GFunctionDebug.Output[6] == 314161); always_check(FunctionDebug.Output[6] == 314161);
always_check(GFunctionDebug.Output[7] == 314162); always_check(FunctionDebug.Output[7] == 314162);
always_check(GFunctionDebug.Output[8] == 18); always_check(FunctionDebug.Output[8] == 18);
always_check(GFunctionDebug.Output[9] == 120); always_check(FunctionDebug.Output[9] == 120);
always_check(GFunctionDebug.Output[10] == 720); always_check(FunctionDebug.Output[10] == 720);
always_check(GFunctionDebug.Output[11] == 5040); always_check(FunctionDebug.Output[11] == 5040);
} }
{ {

View File

@ -14,7 +14,7 @@ NAMESPACE_BEGIN(Testing)
NAMESPACE_UNNAMED_BEGIN NAMESPACE_UNNAMED_BEGIN
int32 GTestObject; int32 TestObject;
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 FElementType = T; using ElementType = T;
using FAllocatorType = Allocator; using AllocatorType = Allocator;
using FReference = T&; using Reference = T&;
using FConstReference = const T&; using ConstReference = const T&;
using FIterator = TIteratorImpl<false>; using Iterator = TIteratorImpl<false>;
using FConstIterator = TIteratorImpl<true >; using ConstIterator = TIteratorImpl<true >;
using FReverseIterator = TReverseIterator< FIterator>; using ReverseIterator = TReverseIterator< Iterator>;
using FConstReverseIterator = TReverseIterator<FConstIterator>; using ConstReverseIterator = TReverseIterator<ConstIterator>;
static_assert(CContiguousIterator< FIterator>); static_assert(CContiguousIterator< Iterator>);
static_assert(CContiguousIterator<FConstIterator>); static_assert(CContiguousIterator<ConstIterator>);
/** 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<FElementType>) explicit TArray(size_t Count) requires (CDefaultConstructible<ElementType>)
{ {
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<FElementType>(Impl.Pointer, Num()); Memory::DefaultConstruct<ElementType>(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 FElementType& InValue) requires (CCopyConstructible<FElementType>) TArray(size_t Count, const ElementType& InValue) requires (CCopyConstructible<ElementType>)
: 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<FElementType, TIteratorReferenceType<I>> && CMovable<FElementType>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>> && CMovable<ElementType>)
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) FElementType(*First++); new (Impl.Pointer + Index) ElementType(*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<FElementType>) TArray(const TArray& InValue) requires (CCopyConstructible<ElementType>)
{ {
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<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num()); Memory::CopyConstruct<ElementType>(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<FElementType>) TArray(TArray&& InValue) requires (CMoveConstructible<ElementType>)
{ {
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<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num()); Memory::MoveConstruct<ElementType>(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<FElementType> IL) requires (CCopyConstructible<FElementType>) : TArray(Iteration::Begin(IL), Iteration::End(IL)) { } FORCEINLINE TArray(initializer_list<ElementType> IL) requires (CCopyConstructible<ElementType>) : 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<FElementType>) TArray& operator=(const TArray& InValue) requires (CCopyable<ElementType>)
{ {
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<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num()); Memory::CopyConstruct<ElementType>(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<FElementType>(Impl.Pointer + Num(), InValue.Impl.Pointer + Num(), InValue.Num() - Num()); Memory::CopyConstruct<ElementType>(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<FElementType>) TArray& operator=(TArray&& InValue) requires (CMovable<ElementType>)
{ {
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<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num()); Memory::MoveConstruct<ElementType>(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<FElementType>(Impl.Pointer + Num(), InValue.Impl.Pointer + Num(), InValue.Num() - Num()); Memory::MoveConstruct<ElementType>(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<FElementType> IL) requires (CCopyable<FElementType>) TArray& operator=(initializer_list<ElementType> IL) requires (CCopyable<ElementType>)
{ {
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<FElementType>(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), Num()); Memory::CopyConstruct<ElementType>(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<FElementType>(Impl.Pointer + Num(), NAMESPACE_REDCRAFT::GetData(IL) + Num(), GetNum(IL) - Num()); Memory::CopyConstruct<ElementType>(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<FElementType>) NODISCARD friend bool operator==(const TArray& LHS, const TArray& RHS) requires (CWeaklyEqualityComparable<ElementType>)
{ {
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<FElementType>) NODISCARD friend auto operator<=>(const TArray& LHS, const TArray& RHS) requires (CSynthThreeWayComparable<ElementType>)
{ {
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. */
FIterator Insert(FConstIterator Iter, const FElementType& InValue) requires (CCopyable<FElementType>) Iterator Insert(ConstIterator Iter, const ElementType& InValue) requires (CCopyable<ElementType>)
{ {
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())
{ {
FElementType* OldAllocation = Impl.Pointer; ElementType* 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<FElementType>(Impl.Pointer, OldAllocation, InsertIndex); Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) FElementType(InValue); new (Impl.Pointer + InsertIndex) ElementType(InValue);
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex); Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
return FIterator(this, Impl.Pointer + InsertIndex); return Iterator(this, Impl.Pointer + InsertIndex);
} }
if (InsertIndex != Num()) if (InsertIndex != Num())
{ {
new (Impl.Pointer + Num()) FElementType(MoveTemp(Impl.Pointer[Num() - 1])); new (Impl.Pointer + Num()) ElementType(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()) FElementType(InValue); else new (Impl.Pointer + Num()) ElementType(InValue);
Impl.ArrayNum = Num() + 1; Impl.ArrayNum = Num() + 1;
return FIterator(this, Impl.Pointer + InsertIndex); return Iterator(this, Impl.Pointer + InsertIndex);
} }
/** Inserts 'InValue' before 'Iter' in the container. */ /** Inserts 'InValue' before 'Iter' in the container. */
FIterator Insert(FConstIterator Iter, FElementType&& InValue) requires (CMovable<FElementType>) Iterator Insert(ConstIterator Iter, ElementType&& InValue) requires (CMovable<ElementType>)
{ {
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())
{ {
FElementType* OldAllocation = Impl.Pointer; ElementType* 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<FElementType>(Impl.Pointer, OldAllocation, InsertIndex); Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) FElementType(MoveTemp(InValue)); new (Impl.Pointer + InsertIndex) ElementType(MoveTemp(InValue));
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex); Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
return FIterator(this, Impl.Pointer + InsertIndex); return Iterator(this, Impl.Pointer + InsertIndex);
} }
if (InsertIndex != Num()) if (InsertIndex != Num())
{ {
new (Impl.Pointer + Num()) FElementType(MoveTemp(Impl.Pointer[Num() - 1])); new (Impl.Pointer + Num()) ElementType(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()) FElementType(MoveTemp(InValue)); else new (Impl.Pointer + Num()) ElementType(MoveTemp(InValue));
Impl.ArrayNum = Num() + 1; Impl.ArrayNum = Num() + 1;
return FIterator(this, Impl.Pointer + InsertIndex); return Iterator(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. */
FIterator Insert(FConstIterator Iter, size_t Count, const FElementType& InValue) requires (CCopyable<FElementType>) Iterator Insert(ConstIterator Iter, size_t Count, const ElementType& InValue) requires (CCopyable<ElementType>)
{ {
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<FElementType, TIteratorReferenceType<I>> template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>
&& CAssignableFrom<FElementType&, TIteratorReferenceType<I>> && CMovable<FElementType>) && CAssignableFrom<ElementType&, TIteratorReferenceType<I>> && CMovable<ElementType>)
FIterator Insert(FConstIterator Iter, I First, S Last) Iterator Insert(ConstIterator 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 FIterator(this, Impl.Pointer + InsertIndex); if (Count == 0) return Iterator(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())
{ {
FElementType* OldAllocation = Impl.Pointer; ElementType* 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<FElementType>(Impl.Pointer, OldAllocation, InsertIndex); Memory::MoveConstruct<ElementType>(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) FElementType(*First++); new (Impl.Pointer + Index) ElementType(*First++);
} }
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + Count, OldAllocation + InsertIndex, NumToDestruct - InsertIndex); Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + Count, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
return FIterator(this, Impl.Pointer + InsertIndex); return Iterator(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) FElementType(MoveTemp(Impl.Pointer[TargetIndex - Count])); new (Impl.Pointer + TargetIndex) ElementType(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) FElementType(*First++); new (Impl.Pointer + TargetIndex) ElementType(*First++);
} }
check(First == Last); check(First == Last);
Impl.ArrayNum = Num() + Count; Impl.ArrayNum = Num() + Count;
return FIterator(this, Impl.Pointer + InsertIndex); return Iterator(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 FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL) requires (CCopyable<FElementType>) FORCEINLINE Iterator Insert(ConstIterator Iter, initializer_list<ElementType> IL) requires (CCopyable<ElementType>)
{ {
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<FElementType, Ts...> && CMovable<FElementType>) template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...> && CMovable<ElementType>)
FIterator Emplace(FConstIterator Iter, Ts&&... Args) Iterator Emplace(ConstIterator 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())
{ {
FElementType* OldAllocation = Impl.Pointer; ElementType* 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<FElementType>(Impl.Pointer, OldAllocation, InsertIndex); Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
new (Impl.Pointer + InsertIndex) FElementType(Forward<Ts>(Args)...); new (Impl.Pointer + InsertIndex) ElementType(Forward<Ts>(Args)...);
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex); Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
return FIterator(this, Impl.Pointer + InsertIndex); return Iterator(this, Impl.Pointer + InsertIndex);
} }
if (InsertIndex != Num()) if (InsertIndex != Num())
{ {
new (Impl.Pointer + Num()) FElementType(MoveTemp(Impl.Pointer[Num() - 1])); new (Impl.Pointer + Num()) ElementType(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] = FElementType(Forward<Ts>(Args)...); Impl.Pointer[InsertIndex] = ElementType(Forward<Ts>(Args)...);
} }
else new (Impl.Pointer + Num()) FElementType(Forward<Ts>(Args)...); else new (Impl.Pointer + Num()) ElementType(Forward<Ts>(Args)...);
Impl.ArrayNum = Num() + 1; Impl.ArrayNum = Num() + 1;
return FIterator(this, Impl.Pointer + InsertIndex); return Iterator(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 FIterator StableErase(FConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<FElementType>) FORCEINLINE Iterator StableErase(ConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<ElementType>)
{ {
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. */
FIterator StableErase(FConstIterator First, FConstIterator Last, bool bAllowShrinking = true) requires (CMovable<FElementType>) Iterator StableErase(ConstIterator First, ConstIterator Last, bool bAllowShrinking = true) requires (CMovable<ElementType>)
{ {
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 FIterator(this, Impl.Pointer + EraseIndex); if (EraseCount == 0) return Iterator(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())
{ {
FElementType* OldAllocation = Impl.Pointer; ElementType* 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<FElementType>(Impl.Pointer, OldAllocation, EraseIndex); Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, EraseIndex);
Memory::MoveConstruct<FElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount); Memory::MoveConstruct<ElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
return FIterator(this, Impl.Pointer + EraseIndex); return Iterator(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 FIterator(this, Impl.Pointer + EraseIndex); return Iterator(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 FIterator Erase(FConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<FElementType>) FORCEINLINE Iterator Erase(ConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<ElementType>)
{ {
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. */
FIterator Erase(FConstIterator First, FConstIterator Last, bool bAllowShrinking = true) requires (CMovable<FElementType>) Iterator Erase(ConstIterator First, ConstIterator Last, bool bAllowShrinking = true) requires (CMovable<ElementType>)
{ {
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 FIterator(this, Impl.Pointer + EraseIndex); if (EraseCount == 0) return Iterator(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())
{ {
FElementType* OldAllocation = Impl.Pointer; ElementType* 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<FElementType>(Impl.Pointer, OldAllocation, EraseIndex); Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, EraseIndex);
Memory::MoveConstruct<FElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount); Memory::MoveConstruct<ElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
Memory::Destruct(OldAllocation, NumToDestruct); Memory::Destruct(OldAllocation, NumToDestruct);
Impl->Deallocate(OldAllocation); Impl->Deallocate(OldAllocation);
return FIterator(this, Impl.Pointer + EraseIndex); return Iterator(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 FIterator(this, Impl.Pointer + EraseIndex); return Iterator(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 FElementType& InValue) requires (CCopyable<FElementType>) FORCEINLINE void PushBack(const ElementType& InValue) requires (CCopyable<ElementType>)
{ {
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(FElementType&& InValue) requires (CMovable<FElementType>) FORCEINLINE void PushBack(ElementType&& InValue) requires (CMovable<ElementType>)
{ {
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<FElementType, Ts...> && CMovable<FElementType>) template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...> && CMovable<ElementType>)
FElementType& EmplaceBack(Ts&&... Args) ElementType& 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())
{ {
FElementType* OldAllocation = Impl.Pointer; ElementType* 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<FElementType>(Impl.Pointer, OldAllocation, Num() - 1); Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num() - 1);
new (Impl.Pointer + Num() - 1) FElementType(Forward<Ts>(Args)...); new (Impl.Pointer + Num() - 1) ElementType(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()) FElementType(Forward<Ts>(Args)...); new (Impl.Pointer + Num()) ElementType(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<FElementType>) FORCEINLINE void PopBack(bool bAllowShrinking = true) requires (CMovable<ElementType>)
{ {
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<FElementType> && CMovable<FElementType>) void SetNum(size_t Count, bool bAllowShrinking = true) requires (CDefaultConstructible<ElementType> && CMovable<ElementType>)
{ {
size_t NumToAllocate = Count; size_t NumToAllocate = Count;
@ -741,8 +741,8 @@ public:
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
FElementType* OldAllocation = Impl.Pointer; ElementType* 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<FElementType>(Impl.Pointer, OldAllocation, NumToDestruct); Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, NumToDestruct);
Memory::DefaultConstruct<FElementType>(Impl.Pointer + NumToDestruct, Num() - NumToDestruct); Memory::DefaultConstruct<ElementType>(Impl.Pointer + NumToDestruct, Num() - NumToDestruct);
} }
else else
{ {
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num()); Memory::MoveConstruct<ElementType>(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<FElementType>(Impl.Pointer + Num(), Count - Num()); Memory::DefaultConstruct<ElementType>(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 FElementType& InValue, bool bAllowShrinking = true) requires (CCopyConstructible<FElementType> && CMovable<FElementType>) void SetNum(size_t Count, const ElementType& InValue, bool bAllowShrinking = true) requires (CCopyConstructible<ElementType> && CMovable<ElementType>)
{ {
size_t NumToAllocate = Count; size_t NumToAllocate = Count;
@ -787,8 +787,8 @@ public:
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
FElementType* OldAllocation = Impl.Pointer; ElementType* 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<FElementType>(Impl.Pointer, OldAllocation, NumToDestruct); Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, NumToDestruct);
for (size_t Index = NumToDestruct; Index != Num(); ++Index) for (size_t Index = NumToDestruct; Index != Num(); ++Index)
{ {
new (Impl.Pointer + Index) FElementType(InValue); new (Impl.Pointer + Index) ElementType(InValue);
} }
} }
else else
{ {
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num()); Memory::MoveConstruct<ElementType>(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) FElementType(InValue); new (Impl.Pointer + Index) ElementType(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<FElementType>) void Reserve(size_t Count) requires (CMovable<ElementType>)
{ {
if (Count <= Max()) return; if (Count <= Max()) return;
const size_t NumToAllocate = Impl->CalculateSlackReserve(Count); const size_t NumToAllocate = Impl->CalculateSlackReserve(Count);
FElementType* OldAllocation = Impl.Pointer; ElementType* 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<FElementType>(Impl.Pointer, OldAllocation, Num()); Memory::MoveConstruct<ElementType>(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;
FElementType* OldAllocation = Impl.Pointer; ElementType* OldAllocation = Impl.Pointer;
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); Impl.Pointer = Impl->Allocate(Max());
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num()); Memory::MoveConstruct<ElementType>(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 FElementType* GetData() { return Impl.Pointer; } NODISCARD FORCEINLINE ElementType* GetData() { return Impl.Pointer; }
NODISCARD FORCEINLINE const FElementType* GetData() const { return Impl.Pointer; } NODISCARD FORCEINLINE const ElementType* 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 FIterator Begin() { return FIterator(this, Impl.Pointer); } NODISCARD FORCEINLINE Iterator Begin() { return Iterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE FConstIterator Begin() const { return FConstIterator(this, Impl.Pointer); } NODISCARD FORCEINLINE ConstIterator Begin() const { return ConstIterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE FIterator End() { return FIterator(this, Impl.Pointer + Num()); } NODISCARD FORCEINLINE Iterator End() { return Iterator(this, Impl.Pointer + Num()); }
NODISCARD FORCEINLINE FConstIterator End() const { return FConstIterator(this, Impl.Pointer + Num()); } NODISCARD FORCEINLINE ConstIterator End() const { return ConstIterator(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 FReverseIterator RBegin() { return FReverseIterator(End()); } NODISCARD FORCEINLINE ReverseIterator RBegin() { return ReverseIterator(End()); }
NODISCARD FORCEINLINE FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); } NODISCARD FORCEINLINE ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
NODISCARD FORCEINLINE FReverseIterator REnd() { return FReverseIterator(Begin()); } NODISCARD FORCEINLINE ReverseIterator REnd() { return ReverseIterator(Begin()); }
NODISCARD FORCEINLINE FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); } NODISCARD FORCEINLINE ConstReverseIterator REnd() const { return ConstReverseIterator(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(FConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); } NODISCARD FORCEINLINE bool IsValidIterator(ConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
/** @return The reference to the requested element. */ /** @return The reference to the requested element. */
NODISCARD FORCEINLINE FElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; } NODISCARD FORCEINLINE ElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
NODISCARD FORCEINLINE const FElementType& operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; } NODISCARD FORCEINLINE const ElementType& 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 FElementType& Front() { return *Begin(); } NODISCARD FORCEINLINE ElementType& Front() { return *Begin(); }
NODISCARD FORCEINLINE const FElementType& Front() const { return *Begin(); } NODISCARD FORCEINLINE const ElementType& Front() const { return *Begin(); }
NODISCARD FORCEINLINE FElementType& Back() { return *(End() - 1); } NODISCARD FORCEINLINE ElementType& Back() { return *(End() - 1); }
NODISCARD FORCEINLINE const FElementType& Back() const { return *(End() - 1); } NODISCARD FORCEINLINE const ElementType& 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<FElementType>) NODISCARD friend FORCEINLINE size_t GetTypeHash(const TArray& A) requires (CHashable<ElementType>)
{ {
size_t Result = 0; size_t Result = 0;
for (FConstIterator Iter = A.Begin(); Iter != A.End(); ++Iter) for (ConstIterator 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<FElementType>) friend void Swap(TArray& A, TArray& B) requires (CMovable<ElementType>)
{ {
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(FAllocatorType, FElementType, Impl) ALLOCATOR_WRAPPER_BEGIN(AllocatorType, ElementType, Impl)
{ {
size_t ArrayNum; size_t ArrayNum;
size_t ArrayMax; size_t ArrayMax;
FElementType* Pointer; ElementType* Pointer;
} }
ALLOCATOR_WRAPPER_END(FAllocatorType, FElementType, Impl) ALLOCATOR_WRAPPER_END(AllocatorType, ElementType, Impl)
private: private:
@ -981,7 +981,7 @@ private:
{ {
public: public:
using FElementType = TRemoveCV<T>; using ElementType = TRemoveCV<T>;
FORCEINLINE TIteratorImpl() = default; FORCEINLINE TIteratorImpl() = default;

View File

@ -29,15 +29,15 @@ class TArrayView
{ {
public: public:
using FElementType = T; using ElementType = T;
using FReference = T&; using Reference = T&;
class FIterator; class Iterator;
using FReverseIterator = TReverseIterator<FIterator>; using ReverseIterator = TReverseIterator<Iterator>;
static_assert(CContiguousIterator<FIterator>); static_assert(CContiguousIterator<Iterator>);
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>(*)[], FElementType(*)[]>) template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], ElementType(*)[]>)
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>(*)[], FElementType(*)[]>) template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], ElementType(*)[]>)
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(FElementType(&InArray)[N]) FORCEINLINE constexpr TArrayView(ElementType(&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(*)[], FElementType(*)[]>) template <typename U, size_t N> requires (CConvertibleTo<U(*)[], ElementType(*)[]>)
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(*)[], FElementType(*)[]>) template <typename U, size_t N> requires (CConvertibleTo<const U(*)[], ElementType(*)[]>)
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(*)[], FElementType(*)[]>) template <typename U, typename Allocator> requires (CConvertibleTo<U(*)[], ElementType(*)[]>)
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(*)[], FElementType(*)[]>) template <typename U, typename Allocator> requires (CConvertibleTo<const U(*)[], ElementType(*)[]>)
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(*)[], FElementType(*)[]>) template <typename U, size_t N> requires ((Extent == DynamicExtent || N == DynamicExtent || N == Extent) && CConvertibleTo<U(*)[], ElementType(*)[]>)
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<FElementType>) NODISCARD friend constexpr bool operator==(TArrayView LHS, TArrayView RHS) requires (CWeaklyEqualityComparable<ElementType>)
{ {
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<FElementType>) NODISCARD friend constexpr auto operator<=>(TArrayView LHS, TArrayView RHS) requires (CSynthThreeWayComparable<ElementType>)
{ {
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<FElementType, Count> First() const NODISCARD FORCEINLINE constexpr TArrayView<ElementType, 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<FElementType, Count>(Begin(), Count); return TArrayView<ElementType, 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<FElementType, DynamicExtent> First(size_t Count) const NODISCARD FORCEINLINE constexpr TArrayView<ElementType, 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<FElementType, DynamicExtent>(Begin(), Count); return TArrayView<ElementType, 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<FElementType, Count> Last() const NODISCARD FORCEINLINE constexpr TArrayView<ElementType, 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<FElementType, Count>(End() - Count, Count); return TArrayView<ElementType, 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<FElementType, DynamicExtent> Last(size_t Count) const NODISCARD FORCEINLINE constexpr TArrayView<ElementType, 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<FElementType, DynamicExtent>(End() - Count, Count); return TArrayView<ElementType, 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<FElementType, SubviewExtent>(Begin() + Offset, Count); return TArrayView<ElementType, SubviewExtent>(Begin() + Offset, Count);
} }
else else
{ {
return TArrayView<FElementType, SubviewExtent>(Begin() + Offset, Num() - Offset); return TArrayView<ElementType, SubviewExtent>(Begin() + Offset, Num() - Offset);
} }
} }
@ -213,20 +213,20 @@ public:
if (Count != DynamicExtent) if (Count != DynamicExtent)
{ {
return TArrayView<FElementType, DynamicExtent>(Begin() + Offset, Count); return TArrayView<ElementType, DynamicExtent>(Begin() + Offset, Count);
} }
else else
{ {
return TArrayView<FElementType, DynamicExtent>(Begin() + Offset, Num() - Offset); return TArrayView<ElementType, 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(FElementType) * Extent : DynamicExtent; constexpr size_t BytesExtent = Extent != DynamicExtent ? sizeof(ElementType) * Extent : DynamicExtent;
if constexpr (!CConst<FElementType>) if constexpr (!CConst<ElementType>)
{ {
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(FElementType) * Extent : DynamicExtent; constexpr size_t BytesExtent = Extent != DynamicExtent ? sizeof(ElementType) * 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 FElementType* GetData() const { return Impl.Pointer; } NODISCARD FORCEINLINE constexpr ElementType* 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 FIterator Begin() const { return FIterator(this, Impl.Pointer); } NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(this, Impl.Pointer); }
NODISCARD FORCEINLINE constexpr FIterator End() const { return FIterator(this, Impl.Pointer + Num()); } NODISCARD FORCEINLINE constexpr Iterator End() const { return Iterator(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 FReverseIterator RBegin() const { return FReverseIterator(End()); } NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() const { return ReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr FReverseIterator REnd() const { return FReverseIterator(Begin()); } NODISCARD FORCEINLINE constexpr ReverseIterator REnd() const { return ReverseIterator(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(FElementType); } NODISCARD FORCEINLINE constexpr size_t NumBytes() const { return Num() * sizeof(ElementType); }
/** @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(FIterator Iter) const { return Begin() <= Iter && Iter <= End(); } NODISCARD FORCEINLINE constexpr bool IsValidIterator(Iterator Iter) const { return Begin() <= Iter && Iter <= End(); }
/** @return The reference to the requested element. */ /** @return The reference to the requested element. */
NODISCARD FORCEINLINE constexpr FReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; } NODISCARD FORCEINLINE constexpr Reference 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 FReference Front() const { return *Begin(); } NODISCARD FORCEINLINE constexpr Reference Front() const { return *Begin(); }
NODISCARD FORCEINLINE constexpr FReference Back() const { return *(End() - 1); } NODISCARD FORCEINLINE constexpr Reference 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<FElementType>) NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(TArrayView A) requires (CHashable<ElementType>)
{ {
size_t Result = 0; size_t Result = 0;
for (FIterator Iter = A.Begin(); Iter != A.End(); ++Iter) for (Iterator 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 { FElementType* Pointer; }; struct FImplWithoutNum { ElementType* Pointer; };
struct FImplWithNum : FImplWithoutNum { size_t ArrayNum; }; struct FImplWithNum : FImplWithoutNum { size_t ArrayNum; };
@ -299,42 +299,42 @@ private:
public: public:
class FIterator final class Iterator final
{ {
public: public:
using FElementType = TRemoveCV<T>; using ElementType = TRemoveCV<T>;
FORCEINLINE constexpr FIterator() = default; FORCEINLINE constexpr Iterator() = default;
FORCEINLINE constexpr FIterator(const FIterator&) = default; FORCEINLINE constexpr Iterator(const Iterator&) = default;
FORCEINLINE constexpr FIterator(FIterator&&) = default; FORCEINLINE constexpr Iterator(Iterator&&) = default;
FORCEINLINE constexpr FIterator& operator=(const FIterator&) = default; FORCEINLINE constexpr Iterator& operator=(const Iterator&) = default;
FORCEINLINE constexpr FIterator& operator=(FIterator&&) = default; FORCEINLINE constexpr Iterator& operator=(Iterator&&) = default;
NODISCARD friend FORCEINLINE constexpr bool operator==(const FIterator& LHS, const FIterator& RHS) { return LHS.Pointer == RHS.Pointer; } NODISCARD friend FORCEINLINE constexpr bool 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 friend FORCEINLINE constexpr strong_ordering operator<=>(const Iterator& LHS, const Iterator& 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 { FIterator Temp = *this + Index; return *Temp; } NODISCARD FORCEINLINE constexpr T& operator[](ptrdiff Index) const { Iterator Temp = *this + Index; return *Temp; }
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--() { --Pointer; CheckThis(); return *this; }
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--(int) { Iterator Temp = *this; --*this; return Temp; }
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; } FORCEINLINE constexpr Iterator& operator-=(ptrdiff Offset) { Pointer -= Offset; CheckThis(); return *this; }
NODISCARD friend FORCEINLINE constexpr FIterator operator+(FIterator Iter, ptrdiff Offset) { FIterator Temp = Iter; Temp += Offset; return Temp; } NODISCARD friend FORCEINLINE constexpr Iterator operator+(Iterator Iter, ptrdiff Offset) { 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 friend FORCEINLINE constexpr Iterator operator+(ptrdiff Offset, Iterator Iter) { Iterator Temp = Iter; Temp += Offset; return Temp; }
NODISCARD FORCEINLINE constexpr FIterator operator-(ptrdiff Offset) const { FIterator Temp = *this; Temp -= Offset; return Temp; } NODISCARD FORCEINLINE constexpr Iterator operator-(ptrdiff Offset) const { Iterator Temp = *this; Temp -= Offset; return Temp; }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIterator& LHS, const FIterator& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Pointer - RHS.Pointer; } NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const Iterator& LHS, const Iterator& 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 FIterator(const TArrayView* InContainer, T* InPointer) FORCEINLINE constexpr Iterator(const TArrayView* InContainer, T* InPointer)
: Owner(InContainer), Pointer(InPointer) : Owner(InContainer), Pointer(InPointer)
{ } { }
# else # else
FORCEINLINE constexpr FIterator(const TArrayView* InContainer, T* InPointer) FORCEINLINE constexpr Iterator(const TArrayView* InContainer, T* InPointer)
: Pointer(InPointer) : Pointer(InPointer)
{ } { }
# endif # endif

View File

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

View File

@ -28,20 +28,20 @@ private:
public: public:
using FElementType = T; using ElementType = T;
using FAllocatorType = Allocator; using AllocatorType = Allocator;
using FReference = T&; using Reference = T&;
using FConstReference = const T&; using ConstReference = const T&;
using FIterator = TIteratorImpl<false>; using Iterator = TIteratorImpl<false>;
using FConstIterator = TIteratorImpl<true >; using ConstIterator = TIteratorImpl<true >;
using FReverseIterator = TReverseIterator< FIterator>; using ReverseIterator = TReverseIterator< Iterator>;
using FConstReverseIterator = TReverseIterator<FConstIterator>; using ConstReverseIterator = TReverseIterator<ConstIterator>;
static_assert(CBidirectionalIterator< FIterator>); static_assert(CBidirectionalIterator< Iterator>);
static_assert(CBidirectionalIterator<FConstIterator>); static_assert(CBidirectionalIterator<ConstIterator>);
/** 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<FElementType>) : TList() explicit TList(size_t Count) requires (CDefaultConstructible<ElementType>) : 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 FElementType& InValue) requires (CCopyable<FElementType>) TList(size_t Count, const ElementType& InValue) requires (CCopyable<ElementType>)
: 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<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, 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<FElementType>) : TList(InValue.Begin(), InValue.End()) { } FORCEINLINE TList(const TList& InValue) requires (CCopyConstructible<ElementType>) : 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<FElementType> IL) requires (CCopyConstructible<FElementType>) : TList(Iteration::Begin(IL), Iteration::End(IL)) { } FORCEINLINE TList(initializer_list<ElementType> IL) requires (CCopyConstructible<ElementType>) : 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<FElementType>) TList& operator=(const TList& InValue) requires (CCopyable<ElementType>)
{ {
if (&InValue == this) UNLIKELY return *this; if (&InValue == this) UNLIKELY return *this;
FIterator ThisIter = Begin(); Iterator ThisIter = Begin();
FConstIterator OtherIter = InValue.Begin(); ConstIterator 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<FElementType> IL) requires (CCopyable<FElementType>) TList& operator=(initializer_list<ElementType> IL) requires (CCopyable<ElementType>)
{ {
FIterator ThisIter = Begin(); Iterator ThisIter = Begin();
const FElementType* OtherIter = Iteration::Begin(IL); const ElementType* 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<FElementType>) NODISCARD friend bool operator==(const TList& LHS, const TList& RHS) requires (CWeaklyEqualityComparable<ElementType>)
{ {
if (LHS.Num() != RHS.Num()) return false; if (LHS.Num() != RHS.Num()) return false;
FConstIterator LHSIter = LHS.Begin(); ConstIterator LHSIter = LHS.Begin();
FConstIterator RHSIter = RHS.Begin(); ConstIterator 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<FElementType>) NODISCARD friend auto operator<=>(const TList& LHS, const TList& RHS) requires (CSynthThreeWayComparable<ElementType>)
{ {
FConstIterator LHSIter = LHS.Begin(); ConstIterator LHSIter = LHS.Begin();
FConstIterator RHSIter = RHS.Begin(); ConstIterator 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 FIterator Insert(FConstIterator Iter, const FElementType& InValue) requires (CCopyConstructible<FElementType>) { return Emplace(Iter, InValue); } FORCEINLINE Iterator Insert(ConstIterator Iter, const ElementType& InValue) requires (CCopyConstructible<ElementType>) { return Emplace(Iter, InValue); }
/** Inserts 'InValue' before 'Iter' in the container. */ /** Inserts 'InValue' before 'Iter' in the container. */
FORCEINLINE FIterator Insert(FConstIterator Iter, FElementType&& InValue) requires (CMoveConstructible<FElementType>) { return Emplace(Iter, MoveTemp(InValue)); } FORCEINLINE Iterator Insert(ConstIterator Iter, ElementType&& InValue) requires (CMoveConstructible<ElementType>) { 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. */
FIterator Insert(FConstIterator Iter, size_t Count, const FElementType& InValue) requires (CCopyConstructible<FElementType>) Iterator Insert(ConstIterator Iter, size_t Count, const ElementType& InValue) requires (CCopyConstructible<ElementType>)
{ {
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<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
FIterator Insert(FConstIterator Iter, I First, S Last) Iterator Insert(ConstIterator Iter, I First, S Last)
{ {
if (First == Last) return FIterator(Iter.Pointer); if (First == Last) return Iterator(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 FIterator(FirstNode); return Iterator(FirstNode);
} }
/** Inserts elements from initializer list before 'Iter' in the container. */ /** Inserts elements from initializer list before 'Iter' in the container. */
FORCEINLINE FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) { return Insert(Iter, Iteration::Begin(IL), Iteration::End(IL)); } FORCEINLINE Iterator Insert(ConstIterator Iter, initializer_list<ElementType> IL) requires (CCopyConstructible<ElementType>) { 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<FElementType, Ts...>) template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...>)
FIterator Emplace(FConstIterator Iter, Ts&&... Args) Iterator Emplace(ConstIterator 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 FIterator(Node); return Iterator(Node);
} }
/** Removes the element at 'Iter' in the container. */ /** Removes the element at 'Iter' in the container. */
FIterator Erase(FConstIterator Iter) Iterator Erase(ConstIterator Iter)
{ {
FNode* NodeToErase = Iter.Pointer; FNode* NodeToErase = Iter.Pointer;
@ -319,11 +319,11 @@ public:
--Impl.ListNum; --Impl.ListNum;
return FIterator(NextNode); return Iterator(NextNode);
} }
/** Removes the elements in the range ['First', 'Last') in the container. */ /** Removes the elements in the range ['First', 'Last') in the container. */
FIterator Erase(FConstIterator First, FConstIterator Last) Iterator Erase(ConstIterator First, ConstIterator 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 FIterator(LastToErase); return Iterator(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 FElementType& InValue) requires (CCopyConstructible<FElementType>) { EmplaceBack(InValue); } FORCEINLINE void PushBack(const ElementType& InValue) requires (CCopyConstructible<ElementType>) { 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(FElementType&& InValue) requires (CMoveConstructible<FElementType>) { EmplaceBack(MoveTemp(InValue)); } FORCEINLINE void PushBack(ElementType&& InValue) requires (CMoveConstructible<ElementType>) { 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<FElementType, Ts...>) template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...>)
FORCEINLINE FReference EmplaceBack(Ts&&... Args) { return *Emplace(End(), Forward<Ts>(Args)...); } FORCEINLINE Reference 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 FElementType& InValue) requires (CCopyConstructible<FElementType>) { EmplaceFront(InValue); } FORCEINLINE void PushFront(const ElementType& InValue) requires (CCopyConstructible<ElementType>) { 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(FElementType&& InValue) requires (CMoveConstructible<FElementType>) { EmplaceFront(MoveTemp(InValue)); } FORCEINLINE void PushFront(ElementType&& InValue) requires (CMoveConstructible<ElementType>) { 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<FElementType, Ts...>) template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...>)
FORCEINLINE FReference EmplaceFront(Ts&&... Args) { return *Emplace(Begin(), Forward<Ts>(Args)...); } FORCEINLINE Reference 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<FElementType>) void SetNum(size_t Count) requires (CDefaultConstructible<ElementType>)
{ {
if (Count == Impl.ListNum) return; if (Count == Impl.ListNum) return;
if (Count < Impl.ListNum) if (Count < Impl.ListNum)
{ {
FIterator First = End(); Iterator 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 FElementType& InValue) requires (CCopyConstructible<FElementType>) void SetNum(size_t Count, const ElementType& InValue) requires (CCopyConstructible<ElementType>)
{ {
if (Count == Impl.ListNum) return; if (Count == Impl.ListNum) return;
if (Count < Impl.ListNum) if (Count < Impl.ListNum)
{ {
FIterator First = End(); Iterator 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 FIterator Begin() { return FIterator(Impl.HeadNode->NextNode); } NODISCARD FORCEINLINE Iterator Begin() { return Iterator(Impl.HeadNode->NextNode); }
NODISCARD FORCEINLINE FConstIterator Begin() const { return FConstIterator(Impl.HeadNode->NextNode); } NODISCARD FORCEINLINE ConstIterator Begin() const { return ConstIterator(Impl.HeadNode->NextNode); }
NODISCARD FORCEINLINE FIterator End() { return FIterator(Impl.HeadNode); } NODISCARD FORCEINLINE Iterator End() { return Iterator(Impl.HeadNode); }
NODISCARD FORCEINLINE FConstIterator End() const { return FConstIterator(Impl.HeadNode); } NODISCARD FORCEINLINE ConstIterator End() const { return ConstIterator(Impl.HeadNode); }
/** @return The reverse iterator to the first or end element. */ /** @return The reverse iterator to the first or end element. */
NODISCARD FORCEINLINE FReverseIterator RBegin() { return FReverseIterator(End()); } NODISCARD FORCEINLINE ReverseIterator RBegin() { return ReverseIterator(End()); }
NODISCARD FORCEINLINE FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); } NODISCARD FORCEINLINE ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
NODISCARD FORCEINLINE FReverseIterator REnd() { return FReverseIterator(Begin()); } NODISCARD FORCEINLINE ReverseIterator REnd() { return ReverseIterator(Begin()); }
NODISCARD FORCEINLINE FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); } NODISCARD FORCEINLINE ConstReverseIterator REnd() const { return ConstReverseIterator(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(FConstIterator Iter) const NODISCARD FORCEINLINE bool IsValidIterator(ConstIterator 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 FElementType& Front() { return *Begin(); } NODISCARD FORCEINLINE ElementType& Front() { return *Begin(); }
NODISCARD FORCEINLINE const FElementType& Front() const { return *Begin(); } NODISCARD FORCEINLINE const ElementType& Front() const { return *Begin(); }
NODISCARD FORCEINLINE FElementType& Back() { return *(End() - 1); } NODISCARD FORCEINLINE ElementType& Back() { return *(End() - 1); }
NODISCARD FORCEINLINE const FElementType& Back() const { return *(End() - 1); } NODISCARD FORCEINLINE const ElementType& 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<FElementType>) NODISCARD friend FORCEINLINE size_t GetTypeHash(const TList& A) requires (CHashable<ElementType>)
{ {
size_t Result = 0; size_t Result = 0;
for (const FElementType& Element : A) for (const ElementType& 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;
FElementType Value; ElementType 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<FAllocatorType, FNode>); static_assert(CMultipleAllocator<AllocatorType, FNode>);
ALLOCATOR_WRAPPER_BEGIN(FAllocatorType, FNode, Impl) ALLOCATOR_WRAPPER_BEGIN(AllocatorType, FNode, Impl)
{ {
FNode* HeadNode; FNode* HeadNode;
size_t ListNum; size_t ListNum;
} }
ALLOCATOR_WRAPPER_END(FAllocatorType, FNode, Impl) ALLOCATOR_WRAPPER_END(AllocatorType, FNode, Impl)
template <bool bConst, typename U> template <bool bConst, typename U>
class TIteratorImpl final class TIteratorImpl final
{ {
public: public:
using FElementType = TRemoveCV<T>; using ElementType = TRemoveCV<T>;
FORCEINLINE TIteratorImpl() = default; FORCEINLINE TIteratorImpl() = default;

View File

@ -25,22 +25,22 @@ private:
public: public:
using FElementType = T; using ElementType = T;
using FReference = T&; using Reference = T&;
using FConstReference = const T&; using ConstReference = const T&;
using FIterator = TIteratorImpl<false>; using Iterator = TIteratorImpl<false>;
using FConstIterator = TIteratorImpl<true >; using ConstIterator = TIteratorImpl<true >;
using FReverseIterator = TReverseIterator< FIterator>; using ReverseIterator = TReverseIterator< Iterator>;
using FConstReverseIterator = TReverseIterator<FConstIterator>; using ConstReverseIterator = TReverseIterator<ConstIterator>;
static_assert(CContiguousIterator< FIterator>); static_assert(CContiguousIterator< Iterator>);
static_assert(CContiguousIterator<FConstIterator>); static_assert(CContiguousIterator<ConstIterator>);
/** 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<FElementType>) NODISCARD friend constexpr bool operator==(const TStaticArray& LHS, const TStaticArray& RHS) requires (CWeaklyEqualityComparable<ElementType>)
{ {
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<FElementType>) NODISCARD friend constexpr auto operator<=>(const TStaticArray& LHS, const TStaticArray& RHS) requires (CSynthThreeWayComparable<ElementType>)
{ {
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 FElementType* GetData() { return _; } NODISCARD FORCEINLINE constexpr ElementType* GetData() { return _; }
NODISCARD FORCEINLINE constexpr const FElementType* GetData() const { return _; } NODISCARD FORCEINLINE constexpr const ElementType* GetData() const { return _; }
/** @return The iterator to the first or end element. */ /** @return The iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr FIterator Begin() { return FIterator(this, _); } NODISCARD FORCEINLINE constexpr Iterator Begin() { return Iterator(this, _); }
NODISCARD FORCEINLINE constexpr FConstIterator Begin() const { return FConstIterator(this, _); } NODISCARD FORCEINLINE constexpr ConstIterator Begin() const { return ConstIterator(this, _); }
NODISCARD FORCEINLINE constexpr FIterator End() { return FIterator(this, _ + Num()); } NODISCARD FORCEINLINE constexpr Iterator End() { return Iterator(this, _ + Num()); }
NODISCARD FORCEINLINE constexpr FConstIterator End() const { return FConstIterator(this, _ + Num()); } NODISCARD FORCEINLINE constexpr ConstIterator End() const { return ConstIterator(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 FReverseIterator RBegin() { return FReverseIterator(End()); } NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() { return ReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); } NODISCARD FORCEINLINE constexpr ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr FReverseIterator REnd() { return FReverseIterator(Begin()); } NODISCARD FORCEINLINE constexpr ReverseIterator REnd() { return ReverseIterator(Begin()); }
NODISCARD FORCEINLINE constexpr FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); } NODISCARD FORCEINLINE constexpr ConstReverseIterator REnd() const { return ConstReverseIterator(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(FConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); } NODISCARD FORCEINLINE constexpr bool IsValidIterator(ConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
/** @return The reference to the requested element. */ /** @return The reference to the requested element. */
NODISCARD FORCEINLINE constexpr FElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return _[Index]; } NODISCARD FORCEINLINE constexpr ElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return _[Index]; }
NODISCARD FORCEINLINE constexpr const FElementType& operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return _[Index]; } NODISCARD FORCEINLINE constexpr const ElementType& 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 FElementType& Front() { return *Begin(); } NODISCARD FORCEINLINE constexpr ElementType& Front() { return *Begin(); }
NODISCARD FORCEINLINE constexpr const FElementType& Front() const { return *Begin(); } NODISCARD FORCEINLINE constexpr const ElementType& Front() const { return *Begin(); }
NODISCARD FORCEINLINE constexpr FElementType& Back() { return *(End() - 1); } NODISCARD FORCEINLINE constexpr ElementType& Back() { return *(End() - 1); }
NODISCARD FORCEINLINE constexpr const FElementType& Back() const { return *(End() - 1); } NODISCARD FORCEINLINE constexpr const ElementType& 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<FElementType>) NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(const TStaticArray& A) requires (CHashable<ElementType>)
{ {
size_t Result = 0; size_t Result = 0;
for (FConstIterator Iter = A.Begin(); Iter != A.End(); ++Iter) for (ConstIterator 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<FElementType>) { Swap(A._, B._); } friend FORCEINLINE constexpr void Swap(TStaticArray& A, TStaticArray& B) requires (CSwappable<ElementType>) { Swap(A._, B._); }
ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT
@ -127,7 +127,7 @@ private:
{ {
public: public:
using FElementType = TRemoveCV<T>; using ElementType = TRemoveCV<T>;
FORCEINLINE constexpr TIteratorImpl() = default; FORCEINLINE constexpr TIteratorImpl() = default;
@ -224,8 +224,6 @@ 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.
@ -247,5 +245,3 @@ 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 FBlockType = InBlockType; using BlockType = InBlockType;
using FElementType = bool; using ElementType = bool;
class FReference; class Reference;
using FConstReference = bool; using ConstReference = bool;
using FIterator = TIteratorImpl<false>; using Iterator = TIteratorImpl<false>;
using FConstIterator = TIteratorImpl<true >; using ConstIterator = TIteratorImpl<true >;
using FReverseIterator = TReverseIterator< FIterator>; using ReverseIterator = TReverseIterator< Iterator>;
using FConstReverseIterator = TReverseIterator<FConstIterator>; using ConstReverseIterator = TReverseIterator<ConstIterator>;
static_assert(CRandomAccessIterator< FIterator>); static_assert(CRandomAccessIterator< Iterator>);
static_assert(CRandomAccessIterator<FConstIterator>); static_assert(CRandomAccessIterator<ConstIterator>);
static constexpr size_t BlockWidth = sizeof(FBlockType) * 8; static constexpr size_t BlockWidth = sizeof(BlockType) * 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(FBlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected"); static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
if constexpr (sizeof(FBlockType) == sizeof(uint8)) if constexpr (sizeof(BlockType) == sizeof(uint8))
{ {
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0); if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
if constexpr (N > 8) Impl[1] = static_cast<FBlockType>(InValue >> 8); if constexpr (N > 8) Impl[1] = static_cast<BlockType>(InValue >> 8);
if constexpr (N > 16) Impl[2] = static_cast<FBlockType>(InValue >> 16); if constexpr (N > 16) Impl[2] = static_cast<BlockType>(InValue >> 16);
if constexpr (N > 24) Impl[3] = static_cast<FBlockType>(InValue >> 24); if constexpr (N > 24) Impl[3] = static_cast<BlockType>(InValue >> 24);
if constexpr (N > 32) Impl[4] = static_cast<FBlockType>(InValue >> 32); if constexpr (N > 32) Impl[4] = static_cast<BlockType>(InValue >> 32);
if constexpr (N > 40) Impl[5] = static_cast<FBlockType>(InValue >> 40); if constexpr (N > 40) Impl[5] = static_cast<BlockType>(InValue >> 40);
if constexpr (N > 48) Impl[6] = static_cast<FBlockType>(InValue >> 48); if constexpr (N > 48) Impl[6] = static_cast<BlockType>(InValue >> 48);
if constexpr (N > 56) Impl[7] = static_cast<FBlockType>(InValue >> 56); if constexpr (N > 56) Impl[7] = static_cast<BlockType>(InValue >> 56);
} }
else if constexpr (sizeof(FBlockType) == sizeof(uint16)) else if constexpr (sizeof(BlockType) == sizeof(uint16))
{ {
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0); if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
if constexpr (N > 16) Impl[1] = static_cast<FBlockType>(InValue >> 16); if constexpr (N > 16) Impl[1] = static_cast<BlockType>(InValue >> 16);
if constexpr (N > 32) Impl[2] = static_cast<FBlockType>(InValue >> 32); if constexpr (N > 32) Impl[2] = static_cast<BlockType>(InValue >> 32);
if constexpr (N > 48) Impl[3] = static_cast<FBlockType>(InValue >> 48); if constexpr (N > 48) Impl[3] = static_cast<BlockType>(InValue >> 48);
} }
else if constexpr (sizeof(FBlockType) == sizeof(uint32)) else if constexpr (sizeof(BlockType) == sizeof(uint32))
{ {
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0); if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
if constexpr (N > 32) Impl[1] = static_cast<FBlockType>(InValue >> 32); if constexpr (N > 32) Impl[1] = static_cast<BlockType>(InValue >> 32);
} }
else if constexpr (sizeof(FBlockType) == sizeof(uint64)) else if constexpr (sizeof(BlockType) == sizeof(uint64))
{ {
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0); if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
} }
else check_no_entry(); else check_no_entry();
constexpr size_t BlockInteger = sizeof(uint64) / sizeof(FBlockType); constexpr size_t BlockInteger = sizeof(uint64) / sizeof(BlockType);
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 FBlockType LastBlockBitmask = LHS.Num() % BlockWidth != 0 ? (1ull << LHS.Num() % BlockWidth) - 1 : -1; const BlockType 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 FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1; const BlockType 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 FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1; const BlockType 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 = [](FBlockType Block) constexpr constexpr auto BlockCount = [](BlockType Block) constexpr
{ {
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected"); static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
if constexpr (sizeof(FBlockType) == sizeof(uint8)) if constexpr (sizeof(BlockType) == 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(FBlockType) == sizeof(uint16)) else if constexpr (sizeof(BlockType) == 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(FBlockType) == sizeof(uint32)) else if constexpr (sizeof(BlockType) == 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(FBlockType) == sizeof(uint64)) else if constexpr (sizeof(BlockType) == 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 FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1; const BlockType 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<FBlockType>(InValue ? -1 : 0); Impl[Index] = static_cast<BlockType>(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[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 FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1; const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
const FBlockType LastBlock = Impl[NumBlocks() - 1] & LastBlockBitmask; const BlockType 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(FBlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected"); static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
if constexpr (sizeof(FBlockType) == sizeof(uint8)) if constexpr (sizeof(BlockType) == 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(FBlockType) == sizeof(uint16)) else if constexpr (sizeof(BlockType) == 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(FBlockType) == sizeof(uint32)) else if constexpr (sizeof(BlockType) == 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(FBlockType) == sizeof(uint64)) else if constexpr (sizeof(BlockType) == 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 FBlockType* GetData() { return Impl; } NODISCARD FORCEINLINE constexpr BlockType* GetData() { return Impl; }
NODISCARD FORCEINLINE constexpr const FBlockType* GetData() const { return Impl; } NODISCARD FORCEINLINE constexpr const BlockType* 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 FIterator Begin() { return FIterator(this, Impl, 0); } NODISCARD FORCEINLINE constexpr Iterator Begin() { return Iterator(this, Impl, 0); }
NODISCARD FORCEINLINE constexpr FConstIterator Begin() const { return FConstIterator(this, Impl, 0); } NODISCARD FORCEINLINE constexpr ConstIterator Begin() const { return ConstIterator(this, Impl, 0); }
NODISCARD FORCEINLINE constexpr FIterator End() { return FIterator(this, Impl, Num()); } NODISCARD FORCEINLINE constexpr Iterator End() { return Iterator(this, Impl, Num()); }
NODISCARD FORCEINLINE constexpr FConstIterator End() const { return FConstIterator(this, Impl, Num()); } NODISCARD FORCEINLINE constexpr ConstIterator End() const { return ConstIterator(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 FReverseIterator RBegin() { return FReverseIterator(End()); } NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() { return ReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); } NODISCARD FORCEINLINE constexpr ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
NODISCARD FORCEINLINE constexpr FReverseIterator REnd() { return FReverseIterator(Begin()); } NODISCARD FORCEINLINE constexpr ReverseIterator REnd() { return ReverseIterator(Begin()); }
NODISCARD FORCEINLINE constexpr FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); } NODISCARD FORCEINLINE constexpr ConstReverseIterator REnd() const { return ConstReverseIterator(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(FConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); } NODISCARD FORCEINLINE constexpr bool IsValidIterator(ConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
/** @return The reference to the requested bit. */ /** @return The reference to the requested bit. */
NODISCARD FORCEINLINE constexpr FReference operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); } NODISCARD FORCEINLINE constexpr Reference operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
NODISCARD FORCEINLINE constexpr FConstReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); } NODISCARD FORCEINLINE constexpr ConstReference 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 FReference Front() { return *Begin(); } NODISCARD FORCEINLINE constexpr Reference Front() { return *Begin(); }
NODISCARD FORCEINLINE constexpr FConstReference Front() const { return *Begin(); } NODISCARD FORCEINLINE constexpr ConstReference Front() const { return *Begin(); }
NODISCARD FORCEINLINE constexpr FReference Back() { return *(End() - 1); } NODISCARD FORCEINLINE constexpr Reference Back() { return *(End() - 1); }
NODISCARD FORCEINLINE constexpr FConstReference Back() const { return *(End() - 1); } NODISCARD FORCEINLINE constexpr ConstReference 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 FBlockType LastBlockBitmask = A.Num() % BlockWidth != 0 ? (1ull << A.Num() % BlockWidth) - 1 : -1; const BlockType 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:
FBlockType Impl[N != 0 ? (N + BlockWidth - 1) / BlockWidth : 1]; BlockType Impl[N != 0 ? (N + BlockWidth - 1) / BlockWidth : 1];
public: public:
class FReference final : private FSingleton class Reference final : private FSingleton
{ {
public: public:
FORCEINLINE constexpr FReference& operator=(bool InValue) { Data = (Data & ~Mask) | (InValue ? Mask : 0); return *this; } FORCEINLINE constexpr Reference& operator=(bool InValue) { Data = (Data & ~Mask) | (InValue ? Mask : 0); return *this; }
FORCEINLINE constexpr FReference& operator=(const FReference& InValue) { *this = static_cast<bool>(InValue); return *this; } FORCEINLINE constexpr Reference& operator=(const Reference& InValue) { *this = static_cast<bool>(InValue); return *this; }
FORCEINLINE constexpr FReference& operator&=(bool InValue) { Data &= InValue ? -1 : ~Mask; return *this; } FORCEINLINE constexpr Reference& operator&=(bool InValue) { Data &= InValue ? -1 : ~Mask; return *this; }
FORCEINLINE constexpr FReference& operator|=(bool InValue) { Data |= InValue ? Mask : 0; return *this; } FORCEINLINE constexpr Reference& operator|=(bool InValue) { Data |= InValue ? Mask : 0; return *this; }
FORCEINLINE constexpr FReference& operator^=(bool InValue) { *this = InValue ^ *this; return *this; } FORCEINLINE constexpr Reference& 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 FReference(FBlockType& InData, FBlockType InMask) FORCEINLINE constexpr Reference(BlockType& InData, BlockType InMask)
: Data(InData), Mask(InMask) : Data(InData), Mask(InMask)
{ } { }
FBlockType& Data; BlockType& Data;
FBlockType Mask; BlockType Mask;
friend FIterator; friend Iterator;
}; };
@ -538,7 +538,7 @@ private:
public: public:
using FElementType = bool; using ElementType = 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 FReference operator*() const requires (!bConst) { CheckThis(true); return FReference(*(Pointer + BitOffset / BlockWidth), 1ull << BitOffset % BlockWidth); } NODISCARD FORCEINLINE constexpr Reference operator*() const requires (!bConst) { CheckThis(true); return Reference(*(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 ConstReference 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 FBlockPtr = TConditional<bConst, const FBlockType*, FBlockType*>; using BlockPtr = TConditional<bConst, const BlockType*, BlockType*>;
FBlockPtr Pointer = nullptr; BlockPtr Pointer = nullptr;
size_t BitOffset = 0; size_t BitOffset = 0;
# if DO_CHECK # if DO_CHECK
FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, FBlockPtr InPointer, size_t Offset) FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, BlockPtr InPointer, size_t Offset)
: Owner(InContainer), Pointer(InPointer), BitOffset(Offset) : Owner(InContainer), Pointer(InPointer), BitOffset(Offset)
{ } { }
# else # else
FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, FBlockPtr InPointer, size_t Offset) FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, BlockPtr 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 FElementType = TRemoveCVRef<T>; using ElementType = 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 FElementType = TRemoveCVRef<T>; using ElementType = 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 FElementType = TIteratorElement<T>; }; template <CIndirectlyReadable T> class TCountedIteratorImpl<T> { public: using ElementType = TIteratorElement<T>; };
NAMESPACE_PRIVATE_END NAMESPACE_PRIVATE_END
@ -34,7 +34,7 @@ class TCountedIterator final : public NAMESPACE_PRIVATE::TCountedIteratorImpl<I>
{ {
public: public:
using FIteratorType = I; using IteratorType = 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(FIteratorType InValue, ptrdiff N) : Current(MoveTemp(InValue)) { check_code({ MaxLength = N; }); } FORCEINLINE constexpr explicit TCountedIterator(IteratorType 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 FIteratorType& GetBase() const& { CheckThis(); return Current; } NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { CheckThis(); return Current; }
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { CheckThis(); return MoveTemp(Current); } NODISCARD FORCEINLINE constexpr IteratorType 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:
FIteratorType Current; IteratorType 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 FElementType = TRemoveCVRef<T>; using ElementType = 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::FConstIterator& InIter) NODISCARD FORCEINLINE constexpr auto MakeInserter(C& Container, const typename C::ConstIterator& 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 FIteratorType = I; using IteratorType = I;
using FElementType = TIteratorElement<I>; using ElementType = 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(FIteratorType InValue) : Current(MoveTemp(InValue)) { } FORCEINLINE constexpr explicit TMoveIterator(IteratorType 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 FIteratorType& GetBase() const& { return Current; } NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; }
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { return MoveTemp(Current); } NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); }
private: private:
FIteratorType Current; IteratorType Current;
}; };
@ -100,7 +100,7 @@ class TMoveSentinel
{ {
public: public:
using FSentinelType = S; using SentinelType = 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(FSentinelType InValue) : Last(InValue) { } FORCEINLINE constexpr explicit TMoveSentinel(SentinelType 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 FSentinelType& GetBase() const& { return Last; } NODISCARD FORCEINLINE constexpr const SentinelType& GetBase() const& { return Last; }
NODISCARD FORCEINLINE constexpr FSentinelType GetBase() && { return MoveTemp(Last); } NODISCARD FORCEINLINE constexpr SentinelType GetBase() && { return MoveTemp(Last); }
private: private:
FSentinelType Last; SentinelType Last;
}; };

View File

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

View File

@ -25,9 +25,9 @@ class TReverseIterator final
{ {
public: public:
using FIteratorType = I; using IteratorType = I;
using FElementType = TIteratorElement<I>; using ElementType = 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(FIteratorType InValue) : Current(InValue) { } FORCEINLINE constexpr explicit TReverseIterator(IteratorType 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 { FIteratorType Temp = GetBase(); return *--Temp; } NODISCARD FORCEINLINE constexpr TIteratorReference<I> operator*() const { IteratorType Temp = GetBase(); return *--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 auto operator->() const requires (requires(const I Iter) { { ToAddress(Iter) } -> CSameAs<TIteratorPointer<I>>; }) { IteratorType 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 FIteratorType& GetBase() const& { return Current; } NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; }
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { return MoveTemp(Current); } NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); }
private: private:
FIteratorType Current; IteratorType 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 FType = TRemoveCV<T>; }; template <typename T> struct TIteratorElementImpl<T*> { using Type = TRemoveCV<T>; };
template <typename I> requires (requires { typename I::FElementType; }) template <typename I> requires (requires { typename I::ElementType; })
struct TIteratorElementImpl<I> { using FType = typename I::FElementType; }; struct TIteratorElementImpl<I> { using Type = typename I::ElementType; };
template <typename I> struct TIteratorPointerImpl { }; template <typename I> struct TIteratorPointerImpl { };
template <typename T> struct TIteratorPointerImpl<T*> { using FType = T*; }; template <typename T> struct TIteratorPointerImpl<T*> { using Type = 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 FType = decltype(DeclVal<I&>().operator->()); }; struct TIteratorPointerImpl<I> { using Type = 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>>::FType; using TIteratorElement = typename NAMESPACE_PRIVATE::TIteratorElementImpl<TRemoveCVRef<I>>::Type;
template <typename I> template <typename I>
using TIteratorPointer = typename NAMESPACE_PRIVATE::TIteratorPointerImpl<TRemoveCVRef<I>>::FType; using TIteratorPointer = typename NAMESPACE_PRIVATE::TIteratorPointerImpl<TRemoveCVRef<I>>::Type;
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 FElementType = TRemoveCVRef<T>; using ElementType = 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 FElementType&, this concept only requires that the return type * The return type may not be const ElementType&, this concept only requires that the return type
* and FElementType has some relationship, such as copy constructible to FElementType if the type is copyable. * and ElementType has some relationship, such as copy constructible to ElementType if the type is copyable.
* This means that returning a proxy class castable to FElementType is also valid. * This means that returning a proxy class castable to ElementType 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 FElementType = TRemoveCVRef<T>; using ElementType = 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 TForElementType<T>& Allocator, T* InPtr, size_t Num, size_t NumAllocated) && requires (typename A::template ForElementType<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 TForElementType /*: private FSingleton*/ class ForElementType /*: private FSingleton*/
{ {
public: public:
TForElementType() = default; ForElementType() = default;
TForElementType(const TForElementType&) = delete; ForElementType(const ForElementType&) = delete;
TForElementType(TForElementType&&) = delete; ForElementType(ForElementType&&) = delete;
TForElementType& operator=(const TForElementType&) = delete; ForElementType& operator=(const ForElementType&) = delete;
TForElementType& operator=(TForElementType&&) = delete; ForElementType& operator=(ForElementType&&) = 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 TForElementType<Type>> Name; PREPROCESSOR_JOIN(T, Name)<typename Allocator::template ForElementType<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 TForElementType /*: private FSingleton*/ class ForElementType /*: private FSingleton*/
{ {
public: public:
TForElementType() = default; ForElementType() = default;
TForElementType(const TForElementType&) = delete; ForElementType(const ForElementType&) = delete;
TForElementType(TForElementType&&) = delete; ForElementType(ForElementType&&) = delete;
TForElementType& operator=(const TForElementType&) = delete; ForElementType& operator=(const ForElementType&) = delete;
TForElementType& operator=(TForElementType&&) = delete; ForElementType& operator=(ForElementType&&) = 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 TForElementType /*: private FSingleton*/ class ForElementType /*: private FSingleton*/
{ {
public: public:
TForElementType() = default; ForElementType() = default;
TForElementType(const TForElementType&) = delete; ForElementType(const ForElementType&) = delete;
TForElementType(TForElementType&&) = delete; ForElementType(ForElementType&&) = delete;
TForElementType& operator=(const TForElementType&) = delete; ForElementType& operator=(const ForElementType&) = delete;
TForElementType& operator=(TForElementType&&) = delete; ForElementType& operator=(ForElementType&&) = 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 TForElementType /*: private FSingleton*/ class ForElementType /*: private FSingleton*/
{ {
public: public:
TForElementType() = default; ForElementType() = default;
TForElementType(const TForElementType&) = delete; ForElementType(const ForElementType&) = delete;
TForElementType(TForElementType&&) = delete; ForElementType(ForElementType&&) = delete;
TForElementType& operator=(const TForElementType&) = delete; ForElementType& operator=(const ForElementType&) = delete;
TForElementType& operator=(TForElementType&&) = delete; ForElementType& operator=(ForElementType&&) = 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>>::FElementType*, RT>; using TRawPointer = TConditional<CVoid<RT>, typename TPointerTraits<TRemoveCVRef<ST>>::ElementType*, 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>>::FElementType; }) && requires { typename TPointerTraits<TRemoveCV<ST>>::ElementType; })
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>>::FElementType; }) && requires { typename TPointerTraits<TRemoveCV<ST>>::ElementType; })
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 FPointerType = T*; using PointerType = T*;
using FElementType = T; using ElementType = T;
static FORCEINLINE constexpr FElementType* ToAddress(FPointerType InPtr) static FORCEINLINE constexpr ElementType* ToAddress(PointerType InPtr)
{ {
return InPtr; return InPtr;
} }
@ -34,29 +34,29 @@ struct TPointerTraits<T(*)[]>
{ {
static constexpr bool bIsPointer = true; static constexpr bool bIsPointer = true;
using FPointerType = T(*)[]; using PointerType = T(*)[];
using FElementType = T; using ElementType = T;
static FORCEINLINE constexpr FElementType* ToAddress(FPointerType InPtr) static FORCEINLINE constexpr ElementType* ToAddress(PointerType 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 FPointerType = TPtr<T>; \ using PointerType = TPtr<T>; \
using FElementType = TPtr<T>::FElementType; \ using ElementType = TPtr<T>::ElementType; \
\ \
static FORCEINLINE constexpr FElementType* ToAddress(const FPointerType& InPtr) \ static FORCEINLINE constexpr ElementType* ToAddress(const PointerType& 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 FRefCounter = TAtomic<size_t>; using RefCounter = TAtomic<size_t>;
// Ensure that counters are lock-free for performance. // Ensure that counters are lock-free for performance.
static_assert(FRefCounter::bIsAlwaysLockFree); static_assert(RefCounter::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.
FRefCounter SharedReferenceCount; RefCounter 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.
FRefCounter WeakReferenceCount; RefCounter 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 FRefCounter::FValueType GetSharedReferenceCount() FORCEINLINE RefCounter::ValueType 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()
{ {
FRefCounter::FValueType OldSharedReferenceCount = GetSharedReferenceCount(); RefCounter::ValueType 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.
FRefCounter::FValueType OldSharedReferenceCount = SharedReferenceCount.FetchSub(1, EMemoryOrder::Release); RefCounter::ValueType 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().
FRefCounter::FValueType OldWeakReferenceCount = WeakReferenceCount.FetchSub(1, EMemoryOrder::Release); RefCounter::ValueType 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 FSharedFromThisType = TSharedFromThis; using SharedFromThisType = 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 FHelper = NAMESPACE_PRIVATE::FSharedHelper; using Helper = NAMESPACE_PRIVATE::FSharedHelper;
public: public:
using FElementType = T; using ElementType = T;
using FWeakType = TWeakPtr<T>; using WeakType = 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 FHelper::CopySharedReference(*this, InValue); } FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return Helper::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 FHelper::CopySharedReference(*this, InValue); } FORCEINLINE TSharedRef& operator=(const TSharedRef<U>& InValue) { return Helper::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 FHelper::MoveSharedReference(*this, MoveTemp(InValue)); } FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return Helper::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 FHelper::MoveSharedReference(*this, MoveTemp(InValue)); } FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return Helper::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::FSharedFromThisType; }) if constexpr (CClass<T> && !CVolatile<T> && requires { typename T::SharedFromThisType; })
{ {
using FSharedFromThisType = typename T::FSharedFromThisType; using SharedFromThisType = T::SharedFromThisType;
if constexpr (CDerivedFrom<T, FSharedFromThisType>) if constexpr (CDerivedFrom<T, SharedFromThisType>)
{ {
if (Pointer != nullptr) if (Pointer != nullptr)
{ {
const FSharedFromThisType& SharedFromThis = *Pointer; const SharedFromThisType& 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 FHelper = NAMESPACE_PRIVATE::FSharedHelper; using Helper = NAMESPACE_PRIVATE::FSharedHelper;
public: public:
using FElementType = T; using ElementType = T;
using FWeakType = TWeakPtr<T>; using WeakType = 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 FHelper::CopySharedReference(*this, InValue); } FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return Helper::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 FHelper::CopySharedReference(*this, InValue); } FORCEINLINE TSharedRef& operator=(const TSharedRef<U>& InValue) { return Helper::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 FHelper::MoveSharedReference(*this, MoveTemp(InValue)); } FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return Helper::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 FHelper::MoveSharedReference(*this, MoveTemp(InValue)); } FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return Helper::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 FHelper = NAMESPACE_PRIVATE::FSharedHelper; using Helper = NAMESPACE_PRIVATE::FSharedHelper;
public: public:
using FElementType = T; using ElementType = T;
using FWeakType = TWeakPtr<T>; using WeakType = 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 FHelper::CopySharedReference(*this, InValue); } FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return Helper::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 FHelper::CopySharedReference(*this, InValue); } FORCEINLINE TSharedPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::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 FHelper::CopySharedReference(*this, InValue); } FORCEINLINE TSharedPtr& operator=(const TSharedRef<U>& InValue) { return Helper::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 FHelper::MoveSharedReference(*this, MoveTemp(InValue)); } FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return Helper::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 FHelper::MoveSharedReference(*this, MoveTemp(InValue)); } FORCEINLINE TSharedPtr& operator=(TSharedPtr<U>&& InValue) { return Helper::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::FSharedFromThisType; }) if constexpr (CClass<T> && !CVolatile<T> && requires { typename T::SharedFromThisType; })
{ {
using FSharedFromThisType = typename T::FSharedFromThisType; using SharedFromThisType = T::SharedFromThisType;
if constexpr (CDerivedFrom<T, FSharedFromThisType>) if constexpr (CDerivedFrom<T, SharedFromThisType>)
{ {
if (Pointer != nullptr) if (Pointer != nullptr)
{ {
const FSharedFromThisType& SharedFromThis = *Pointer; const SharedFromThisType& 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 FHelper = NAMESPACE_PRIVATE::FSharedHelper; using Helper = NAMESPACE_PRIVATE::FSharedHelper;
public: public:
using FElementType = T; using ElementType = T;
using FWeakType = TWeakPtr<T>; using WeakType = 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 FHelper::CopySharedReference(*this, InValue); } FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return Helper::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 FHelper::CopySharedReference(*this, InValue); } FORCEINLINE TSharedPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::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 FHelper::CopySharedReference(*this, InValue); } FORCEINLINE TSharedPtr& operator=(const TSharedRef<U>& InValue) { return Helper::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 FHelper::MoveSharedReference(*this, MoveTemp(InValue)); } FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return Helper::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 FHelper::MoveSharedReference(*this, MoveTemp(InValue)); } FORCEINLINE TSharedPtr& operator=(TSharedPtr<U>&& InValue) { return Helper::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 FHelper = NAMESPACE_PRIVATE::FSharedHelper; using Helper = NAMESPACE_PRIVATE::FSharedHelper;
public: public:
using FElementType = T; using ElementType = 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 FHelper::CopyWeakReference(*this, InValue); } FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return Helper::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 FHelper::CopyWeakReference(*this, InValue); } FORCEINLINE TWeakPtr& operator=(const TWeakPtr<U>& InValue) { return Helper::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 FHelper::MoveWeakReference(*this, MoveTemp(InValue)); } FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return Helper::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 FHelper::MoveWeakReference(*this, MoveTemp(InValue)); } FORCEINLINE TWeakPtr& operator=(TWeakPtr<U>&& InValue) { return Helper::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 FHelper::CopyWeakReference(*this, InValue); } FORCEINLINE TWeakPtr& operator=(const TSharedRef<U>& InValue) { return Helper::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 FHelper::CopyWeakReference(*this, InValue); } FORCEINLINE TWeakPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::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 FHelper = NAMESPACE_PRIVATE::FSharedHelper; using Helper = NAMESPACE_PRIVATE::FSharedHelper;
public: public:
using FElementType = T; using ElementType = 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 FHelper::CopyWeakReference(*this, InValue); } FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return Helper::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 FHelper::CopyWeakReference(*this, InValue); } FORCEINLINE TWeakPtr& operator=(const TWeakPtr<U>& InValue) { return Helper::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 FHelper::MoveWeakReference(*this, MoveTemp(InValue)); } FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return Helper::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 FHelper::MoveWeakReference(*this, MoveTemp(InValue)); } FORCEINLINE TWeakPtr& operator=(TWeakPtr<U>&& InValue) { return Helper::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 FHelper::CopyWeakReference(*this, InValue); } FORCEINLINE TWeakPtr& operator=(const TSharedRef<U>& InValue) { return Helper::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 FHelper::CopyWeakReference(*this, InValue); } FORCEINLINE TWeakPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::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 FElementType = T; using ElementType = T;
using FDeleterType = E; using DeleterType = 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 FElementType = T; using ElementType = T;
using FDeleterType = E; using DeleterType = 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 FElementType = T; using ElementType = T;
using FDeleterType = E; using DeleterType = 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 FElementType = T; using ElementType = T;
using FDeleterType = E; using DeleterType = 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,8 +42,6 @@ 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.")
@ -79,8 +77,6 @@ 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,21 +12,17 @@ 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
// ReSharper disable CppInconsistentNaming typedef NAMESPACE_STD::partial_ordering partial_ordering;
typedef NAMESPACE_STD::weak_ordering weak_ordering;
using partial_ordering = NAMESPACE_STD::partial_ordering; typedef NAMESPACE_STD::strong_ordering strong_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 FType = strong_ordering; }; template<> struct TCommonComparisonCategoryBasic<0> { using Type = strong_ordering; };
template<> struct TCommonComparisonCategoryBasic<2> { using FType = partial_ordering; }; template<> struct TCommonComparisonCategoryBasic<2> { using Type = partial_ordering; };
template<> struct TCommonComparisonCategoryBasic<4> { using FType = weak_ordering; }; template<> struct TCommonComparisonCategoryBasic<4> { using Type = weak_ordering; };
template<> struct TCommonComparisonCategoryBasic<6> { using FType = partial_ordering; }; template<> struct TCommonComparisonCategoryBasic<6> { using Type = partial_ordering; };
template <typename... Ts> template <typename... Ts>
struct TCommonComparisonCategoryImpl struct TCommonComparisonCategoryImpl
@ -36,13 +32,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...>::FType; using TCommonComparisonCategory = typename NAMESPACE_PRIVATE::TCommonComparisonCategoryImpl<Ts...>::Type;
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 FElementType = TRemoveCV<T>; using ElementType = TRemoveCV<T>;
FORCEINLINE constexpr TConstantIterator() = default; FORCEINLINE constexpr TConstantIterator() = default;
@ -70,7 +70,7 @@ class TConstantIterator<T&> final
{ {
public: public:
using FElementType = TRemoveCV<T>; using ElementType = TRemoveCV<T>;
FORCEINLINE constexpr TConstantIterator() = default; FORCEINLINE constexpr TConstantIterator() = default;
@ -115,14 +115,14 @@ class TCountedIterator<TConstantIterator<T>> final
{ {
public: public:
using FIteratorType = TConstantIterator<T>; using IteratorType = TConstantIterator<T>;
using FElementType = typename TConstantIterator<T>::FElementType; using ElementType = typename TConstantIterator<T>::ElementType;
# if DO_CHECK # if DO_CHECK
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<FIteratorType>) : Length(1), MaxLength(0) { } FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<IteratorType>) : Length(1), MaxLength(0) { }
# else # else
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<FIteratorType>) = default; FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<IteratorType>) = 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 = FIteratorType> requires (!CSameAs<TCountedIterator, TRemoveCVRef<U>> && CConstructibleFrom<FIteratorType, U>) template <typename U = IteratorType> requires (!CSameAs<TCountedIterator, TRemoveCVRef<U>> && CConstructibleFrom<IteratorType, 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<FIteratorType, J> && CConstructibleFrom<FIteratorType, const J&>) template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConstructibleFrom<IteratorType, const J&>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, FIteratorType>) TCountedIterator(const TCountedIterator<J>& InValue) : Current(InValue.Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); } FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, IteratorType>) TCountedIterator(const TCountedIterator<J>& InValue) : Current(InValue.Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConstructibleFrom<FIteratorType, J>) template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConstructibleFrom<IteratorType, J>)
FORCEINLINE constexpr explicit (!CConvertibleTo<J&&, FIteratorType>) TCountedIterator(TCountedIterator<J>&& InValue) : Current(MoveTemp(InValue).Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); } FORCEINLINE constexpr explicit (!CConvertibleTo<J&&, IteratorType>) TCountedIterator(TCountedIterator<J>&& InValue) : Current(MoveTemp(InValue).Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConvertibleTo<const J&, FIteratorType> && CAssignableFrom<FIteratorType&, const J&>) template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConvertibleTo<const J&, IteratorType> && CAssignableFrom<IteratorType&, 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<FIteratorType, J> && CConvertibleTo<J&&, FIteratorType> && CAssignableFrom<FIteratorType&, J&&>) template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConvertibleTo<J&&, IteratorType> && CAssignableFrom<IteratorType&, 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<FIteratorType> J> template <CCommonType<IteratorType> 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<FIteratorType> J> template <CCommonType<IteratorType> 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<FIteratorType> J> template <CCommonType<IteratorType> 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 FIteratorType& GetBase() const& { CheckThis(); return Current; } NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { CheckThis(); return Current; }
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { CheckThis(); return MoveTemp(Current); } NODISCARD FORCEINLINE constexpr IteratorType 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:
FIteratorType Current; IteratorType Current;
ptrdiff Length; ptrdiff Length;
# if DO_CHECK # if DO_CHECK
ptrdiff MaxLength; ptrdiff MaxLength;

View File

@ -9,8 +9,6 @@ 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)]]
@ -44,8 +42,6 @@ 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,8 +14,6 @@ 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
@ -529,8 +527,6 @@ 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 FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>; using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A); auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
return (IntegralValue & FTraits::ExponentMask) == FTraits::ExponentMask && (IntegralValue & FTraits::MantissaMask) == 0; return (IntegralValue & Traits::ExponentMask) == Traits::ExponentMask && (IntegralValue & Traits::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 FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>; using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A); auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
return (IntegralValue & FTraits::ExponentMask) == FTraits::ExponentMask && (IntegralValue & FTraits::MantissaMask) != 0; return (IntegralValue & Traits::ExponentMask) == Traits::ExponentMask && (IntegralValue & Traits::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 FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>; using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A); auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
return (IntegralValue & FTraits::ExponentMask) != 0 && (IntegralValue & FTraits::ExponentMask) != FTraits::ExponentMask; return (IntegralValue & Traits::ExponentMask) != 0 && (IntegralValue & Traits::ExponentMask) != Traits::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 FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>; using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A); auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
return (IntegralValue & FTraits::ExponentMask) == 0 && (IntegralValue & FTraits::MantissaMask) != 0; return (IntegralValue & Traits::ExponentMask) == 0 && (IntegralValue & Traits::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 FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>; using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A); auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
return (IntegralValue & FTraits::SignMask) >> FTraits::SignShift; return (IntegralValue & Traits::SignMask) >> Traits::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 FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>; using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A); auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
return ((IntegralValue & FTraits::ExponentMask) >> FTraits::ExponentShift) - FTraits::ExponentBias; return ((IntegralValue & Traits::ExponentMask) >> Traits::ExponentShift) - Traits::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 FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>; using Traits = 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 FTraits::FIntegralT>(1) << FTraits::MantissaBits), TEXT("Illegal payload. It must be less than 2^MantissaBits.")); checkf(Payload < (static_cast<typename Traits::FIntegralT>(1) << Traits::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 FTraits::FIntegralT ValidPayload = Payload & FTraits::MantissaMask; typename Traits::FIntegralT ValidPayload = Payload & Traits::MantissaMask;
return Math::BitCast<T>(ValidPayload | FTraits::ExponentMask); return Math::BitCast<T>(ValidPayload | Traits::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 FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>; using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A); auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
return IntegralValue & FTraits::MantissaMask; return IntegralValue & Traits::MantissaMask;
} }
/** @return The NaN payload of the given value. */ /** @return The NaN payload of the given value. */

View File

@ -2,7 +2,6 @@
#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"
@ -149,15 +148,6 @@ 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 FElementType = T; using ElementType = T;
using FReference = T&; using Reference = T&;
using FIterator = T*; using Iterator = T*;
using FSentinel = T*; using Sentinel = T*;
FORCEINLINE constexpr TEmptyView() = default; FORCEINLINE constexpr TEmptyView() = default;
NODISCARD static FORCEINLINE constexpr FIterator Begin() { return nullptr; } NODISCARD static FORCEINLINE constexpr Iterator Begin() { return nullptr; }
NODISCARD static FORCEINLINE constexpr FSentinel End() { return nullptr; } NODISCARD static FORCEINLINE constexpr Sentinel 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 FElementType = T; using ElementType = T;
using FReference = T&; using Reference = T&;
using FConstReference = const T&; using ConstReference = const T&;
using FIterator = T*; using Iterator = T*;
using FConstIterator = const T*; using ConstIterator = const T*;
using FSentinel = T*; using Sentinel = T*;
using FConstSentinel = const T*; using ConstSentinel = 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 FIterator Begin() { return GetData(); } FORCEINLINE constexpr Iterator Begin() { return GetData(); }
FORCEINLINE constexpr FConstIterator Begin() const { return GetData(); } FORCEINLINE constexpr ConstIterator Begin() const { return GetData(); }
FORCEINLINE constexpr FSentinel End() { return GetData() + 1; } FORCEINLINE constexpr Sentinel End() { return GetData() + 1; }
FORCEINLINE constexpr FConstSentinel End() const { return GetData() + 1; } FORCEINLINE constexpr ConstSentinel 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 FElementType = TRemoveCV<W>; using ElementType = TRemoveCV<W>;
using FReference = W; using Reference = W;
using FIterator = FIteratorImpl; using Iterator = FIteratorImpl;
using FSentinel = TConditional<CSameAs<W, S>, FIteratorImpl, FSentinelImpl>; using Sentinel = 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(FIterator InFirst, FSentinel InLast) : First(InFirst.Value), Last(InLast.Value) { } FORCEINLINE constexpr explicit TIotaView(Iterator InFirst, Sentinel InLast) : First(InFirst.Value), Last(InLast.Value) { }
FORCEINLINE constexpr explicit TIotaView(FIterator InFirst, FUnreachableSentinel) requires (CSameAs<S, FUnreachableSentinel>) : First(InFirst.Value) { } FORCEINLINE constexpr explicit TIotaView(Iterator InFirst, FUnreachableSentinel) requires (CSameAs<S, FUnreachableSentinel>) : First(InFirst.Value) { }
NODISCARD FORCEINLINE constexpr FIterator Begin() const { return FIterator(First); } NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(First); }
NODISCARD FORCEINLINE constexpr FSentinel End() const { return FSentinel(Last); } NODISCARD FORCEINLINE constexpr Sentinel End() const { return Sentinel(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 FElementType = TRemoveCV<W>; using ElementType = 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 FReference operator*() const { return Value; } NODISCARD FORCEINLINE constexpr Reference 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 FElementType = W; using ElementType = W;
using FReference = const W&; using Reference = const W&;
using FIterator = FIteratorImpl; using Iterator = FIteratorImpl;
using FSentinel = TConditional<bIsUnreachable, FUnreachableSentinel, FIterator>; using Sentinel = TConditional<bIsUnreachable, FUnreachableSentinel, Iterator>;
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 FIterator Begin() const { return FIterator(Value, 0); } NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(Value, 0); }
NODISCARD FORCEINLINE constexpr FSentinel End() const NODISCARD FORCEINLINE constexpr Sentinel End() const
{ {
if constexpr (bIsUnreachable) if constexpr (bIsUnreachable)
{ {
return UnreachableSentinel; return UnreachableSentinel;
} }
else return FSentinel(Value, Count); else return Sentinel(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 FElementType = W; using ElementType = 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 FReference operator*() const { return *Ptr; } NODISCARD FORCEINLINE constexpr Reference 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 FReference operator[](ptrdiff) const { return *Ptr; } NODISCARD FORCEINLINE constexpr Reference 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,7 +2,6 @@
#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"
@ -31,20 +30,20 @@ private:
public: public:
using FElementType = TRangeElement<V>; using ElementType = TRangeElement<V>;
using FReference = TRangeReference<V>; using Reference = TRangeReference<V>;
using FIterator = FIteratorImpl; using Iterator = FIteratorImpl;
using FSentinel = TConditional<CCommonRange<V>, FIteratorImpl, FSentinelImpl>; using Sentinel = 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 FIterator Begin() NODISCARD FORCEINLINE constexpr Iterator Begin()
{ {
FIterator Iter(*this, Range::Begin(Base)); Iterator Iter(*this, Range::Begin(Base));
do do
{ {
@ -61,7 +60,7 @@ public:
return Iter; return Iter;
} }
NODISCARD FORCEINLINE constexpr FSentinel End() { return FSentinel(*this, Range::End(Base)); } NODISCARD FORCEINLINE constexpr Sentinel End() { return Sentinel(*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); }
@ -79,7 +78,7 @@ private:
public: public:
using FElementType = TIteratorElementType<TRangeIterator<V>>; using ElementType = 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.
@ -175,10 +174,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 TAdaptorClosure([&Predicate]<CViewableRange R> requires (requires { Range::Filter(DeclVal<R&&>(), DeclVal<Pred&&>()); }) (R&& Base) return [&Predicate]<CViewableRange R> requires (requires { TFilterView(DeclVal<R&&>(), DeclVal<Pred&&>()); }) (R&& Base)
{ {
return Range::Filter(Forward<R>(Base), Forward<Pred>(Predicate)); return TFilterView(Forward<R>(Base), Forward<Pred>(Predicate));
}); };
} }
NAMESPACE_END(Range) NAMESPACE_END(Range)

View File

@ -1,119 +0,0 @@
#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,7 +4,6 @@
#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,7 +2,6 @@
#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"
@ -89,7 +88,7 @@ private:
public: public:
using FElementType = TRemoveCVRef<TInvokeResult<FFunc&, TRangeReference<FBase>>>; using ElementType = TRemoveCVRef<TInvokeResult<FFunc&, TRangeReference<FBase>>>;
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<FBase>>) = default; FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<FBase>>) = default;
@ -222,10 +221,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 TAdaptorClosure([&Func]<CViewableRange R> requires (requires { Range::Transform(DeclVal<R&&>(), DeclVal<F&&>()); }) (R&& Base) return [&Func]<CViewableRange R> requires (requires { TTransformView(DeclVal<R&&>(), DeclVal<F&&>()); }) (R&& Base)
{ {
return Range::Transform(Forward<R>(Base), Forward<F>(Func)); return TTransformView(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)
/** An interface class template for defining a view. Not directly instantiable. */ /** A helper class template for defining a view interface. 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 FElementType = TIteratorElementType<I>; using ElementType = 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 FCharType = T; using CharType = 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<FCharType, char> ? MB_LEN_MAX : CSameAs<CharType, char> ? MB_LEN_MAX :
CSameAs<FCharType, wchar> ? CSameAs<CharType, wchar> ?
PLATFORM_WINDOWS ? 2 : PLATFORM_WINDOWS ? 2 :
PLATFORM_LINUX ? 1 : 1 : PLATFORM_LINUX ? 1 : 1 :
CSameAs<FCharType, u8char> ? 4 : CSameAs<CharType, u8char> ? 4 :
CSameAs<FCharType, u16char> ? 2 : CSameAs<CharType, u16char> ? 2 :
CSameAs<FCharType, u32char> ? 1 : 1; CSameAs<CharType, 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(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsValid(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, u8char>) if constexpr (CSameAs<CharType, u8char>)
{ {
if ((InChar & 0b10000000) == 0b00000000) return true; if ((InChar & 0b10000000) == 0b00000000) return true;
return false; return false;
} }
else if constexpr (CSameAs<FCharType, u16char> || CSameAs<FCharType, u32char>) else if constexpr (CSameAs<CharType, u16char> || CSameAs<CharType, 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<FCharType, wchar>)) else if constexpr (PLATFORM_WINDOWS && (CSameAs<CharType, 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<FCharType, wchar>)) else if constexpr (PLATFORM_LINUX && (CSameAs<CharType, wchar>))
{ {
return TChar::IsValid(static_cast<u32char>(InChar)); return TChar::IsValid(static_cast<u32char>(InChar));
} }
else static_assert(sizeof(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsNonch(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsNonch(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, u8char>) if constexpr (CSameAs<CharType, u8char>)
{ {
return false; return false;
} }
else if constexpr (CSameAs<FCharType, u16char>) else if constexpr (CSameAs<CharType, 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<FCharType, u32char>) else if constexpr (CSameAs<CharType, 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<FCharType, wchar>)) else if constexpr (PLATFORM_WINDOWS && (CSameAs<CharType, 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<FCharType, wchar>)) else if constexpr (PLATFORM_LINUX && (CSameAs<CharType, wchar>))
{ {
return TChar::IsNonch(static_cast<u32char>(InChar)); return TChar::IsNonch(static_cast<u32char>(InChar));
} }
else static_assert(sizeof(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsASCII(FCharType InChar = LITERAL(FCharType, '\0')) NODISCARD FORCEINLINE static constexpr bool IsASCII(CharType InChar = LITERAL(CharType, '\0'))
{ {
if constexpr (CSameAs<FCharType, char>) if constexpr (CSameAs<CharType, 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<FCharType, wchar>) else if constexpr (CSameAs<CharType, 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<FCharType, u8char> || CSameAs<FCharType, u16char> || CSameAs<FCharType, u32char> || CSameAs<FCharType, unicodechar>) else if constexpr (CSameAs<CharType, u8char> || CSameAs<CharType, u16char> || CSameAs<CharType, u32char> || CSameAs<CharType, unicodechar>)
{ {
return InChar <= 0x7F; return InChar <= 0x7F;
} }
else static_assert(sizeof(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsAlnum(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsAlnum(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, 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(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsAlpha(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, 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<FCharType, u8char>) else if constexpr (CSameAs<CharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -258,29 +258,29 @@ struct TChar
return false; return false;
} }
else if constexpr (CSameAs<FCharType, u16char> || CSameAs<FCharType, u32char>) else if constexpr (CSameAs<CharType, u16char> || CSameAs<CharType, u32char>)
{ {
checkf(InChar <= LITERAL(FCharType, '\u007F'), TEXT("TChar::IsAlpha() only supports basic latin block.")); checkf(InChar <= LITERAL(CharType, '\u007F'), TEXT("TChar::IsAlpha() only supports basic latin block."));
if (InChar > LITERAL(FCharType, '\u007F')) return false; if (InChar > LITERAL(CharType, '\u007F')) return false;
return TChar<u8char>::IsAlpha(static_cast<u8char>(InChar)); return TChar<u8char>::IsAlpha(static_cast<u8char>(InChar));
} }
else static_assert(sizeof(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsLower(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsLower(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, 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<FCharType, u8char>) else if constexpr (CSameAs<CharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -291,7 +291,7 @@ struct TChar
return false; return false;
} }
else if constexpr (CSameAs<FCharType, u16char>) else if constexpr (CSameAs<CharType, 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<FCharType, u32char>) else if constexpr (CSameAs<CharType, 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(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsUpper(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsUpper(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, 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<FCharType, u8char>) else if constexpr (CSameAs<CharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -333,7 +333,7 @@ struct TChar
return false; return false;
} }
else if constexpr (CSameAs<FCharType, u16char>) else if constexpr (CSameAs<CharType, 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<FCharType, u32char>) else if constexpr (CSameAs<CharType, 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(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsDigit(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsDigit(CharType InChar)
{ {
static_assert(TChar::IsASCII()); static_assert(TChar::IsASCII());
/* <U0030>..<U0039>; */ /* <U0030>..<U0039>; */
return InChar >= LITERAL(FCharType, '0') && InChar <= LITERAL(FCharType, '9'); return InChar >= LITERAL(CharType, '0') && InChar <= LITERAL(CharType, '9');
} }
NODISCARD FORCEINLINE static constexpr bool IsDigit(FCharType InChar, unsigned Base) NODISCARD FORCEINLINE static constexpr bool IsDigit(CharType 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(FCharType, '0') && InChar < LITERAL(FCharType, '0') + static_cast<signed>(Base); bResult |= InChar >= LITERAL(CharType, '0') && InChar < LITERAL(CharType, '0') + static_cast<signed>(Base);
/* <U0041>..<U0046>; */ /* <U0041>..<U0046>; */
bResult |= InChar >= LITERAL(FCharType, 'a') && InChar < LITERAL(FCharType, 'a') + static_cast<signed>(Base) - 10; bResult |= InChar >= LITERAL(CharType, 'a') && InChar < LITERAL(CharType, 'a') + static_cast<signed>(Base) - 10;
/* <U0061>..<U0066>; */ /* <U0061>..<U0066>; */
bResult |= InChar >= LITERAL(FCharType, 'A') && InChar < LITERAL(FCharType, 'A') + static_cast<signed>(Base) - 10; bResult |= InChar >= LITERAL(CharType, 'A') && InChar < LITERAL(CharType, 'A') + static_cast<signed>(Base) - 10;
return bResult; return bResult;
} }
NODISCARD FORCEINLINE static constexpr bool IsCntrl(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsCntrl(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, 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<FCharType, u8char>) else if constexpr (CSameAs<CharType, 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<FCharType, u16char>) else if constexpr (CSameAs<CharType, 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<FCharType, u32char>) else if constexpr (CSameAs<CharType, 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(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsGraph(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsGraph(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, 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<FCharType, u8char>) else if constexpr (CSameAs<CharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -440,7 +440,7 @@ struct TChar
return false; return false;
} }
else if constexpr (CSameAs<FCharType, u16char>) else if constexpr (CSameAs<CharType, 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<FCharType, u32char>) else if constexpr (CSameAs<CharType, 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(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsSpace(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsSpace(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, 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<FCharType, u8char>) else if constexpr (CSameAs<CharType, u8char>)
{ {
/* /*
* ISO/IEC 6429 * ISO/IEC 6429
@ -488,7 +488,7 @@ struct TChar
return false; return false;
} }
else if constexpr (CSameAs<FCharType, u16char>) else if constexpr (CSameAs<CharType, u16char>)
{ {
/* /*
* ISO/IEC 6429 * ISO/IEC 6429
@ -533,7 +533,7 @@ struct TChar
return false; return false;
} }
else if constexpr (CSameAs<FCharType, u32char>) else if constexpr (CSameAs<CharType, u32char>)
{ {
/* /*
* ISO/IEC 6429 * ISO/IEC 6429
@ -578,26 +578,26 @@ struct TChar
return false; return false;
} }
else static_assert(sizeof(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsBlank(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsBlank(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, 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<FCharType, u8char>) else if constexpr (CSameAs<CharType, u8char>)
{ {
/* <U0009>;<U0020>; */ /* <U0009>;<U0020>; */
return InChar == U8TEXT('\u0009') || InChar == U8TEXT('\u0020'); return InChar == U8TEXT('\u0009') || InChar == U8TEXT('\u0020');
} }
else if constexpr (CSameAs<FCharType, u16char>) else if constexpr (CSameAs<CharType, 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<FCharType, u32char>) else if constexpr (CSameAs<CharType, 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(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsPrint(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsPrint(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, 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<FCharType, u8char>) else if constexpr (CSameAs<CharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -643,7 +643,7 @@ struct TChar
return false; return false;
} }
else if constexpr (CSameAs<FCharType, u16char>) else if constexpr (CSameAs<CharType, 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<FCharType, u32char>) else if constexpr (CSameAs<CharType, 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(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr bool IsPunct(FCharType InChar) NODISCARD FORCEINLINE static constexpr bool IsPunct(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, 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<FCharType, u8char>) else if constexpr (CSameAs<CharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -689,7 +689,7 @@ struct TChar
return false; return false;
} }
else if constexpr (CSameAs<FCharType, u16char>) else if constexpr (CSameAs<CharType, 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<FCharType, u32char>) else if constexpr (CSameAs<CharType, 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(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return false; return false;
} }
NODISCARD FORCEINLINE static constexpr FCharType ToLower(FCharType InChar) NODISCARD FORCEINLINE static constexpr CharType ToLower(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
{ {
NAMESPACE_STD::locale Loc(""); NAMESPACE_STD::locale Loc("");
return static_cast<FCharType>(NAMESPACE_STD::tolower(InChar, Loc)); return static_cast<CharType>(NAMESPACE_STD::tolower(InChar, Loc));
} }
else if constexpr (CSameAs<FCharType, u8char>) else if constexpr (CSameAs<CharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -737,7 +737,7 @@ struct TChar
return InChar; return InChar;
} }
else if constexpr (CSameAs<FCharType, u16char>) else if constexpr (CSameAs<CharType, 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<FCharType, u32char>) else if constexpr (CSameAs<CharType, 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(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return InChar; return InChar;
} }
NODISCARD FORCEINLINE static constexpr FCharType ToUpper(FCharType InChar) NODISCARD FORCEINLINE static constexpr CharType ToUpper(CharType InChar)
{ {
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>) if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
{ {
NAMESPACE_STD::locale Loc(""); NAMESPACE_STD::locale Loc("");
return static_cast<FCharType>(NAMESPACE_STD::toupper(InChar, Loc)); return static_cast<CharType>(NAMESPACE_STD::toupper(InChar, Loc));
} }
else if constexpr (CSameAs<FCharType, u8char>) else if constexpr (CSameAs<CharType, u8char>)
{ {
/* /*
* BASIC LATIN * BASIC LATIN
@ -785,7 +785,7 @@ struct TChar
return InChar; return InChar;
} }
else if constexpr (CSameAs<FCharType, u16char>) else if constexpr (CSameAs<CharType, 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<FCharType, u32char>) else if constexpr (CSameAs<CharType, 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(FCharType) == -1, "Unsupported character type"); else static_assert(sizeof(CharType) == -1, "Unsupported character type");
return InChar; return InChar;
} }
NODISCARD FORCEINLINE static constexpr unsigned ToDigit(FCharType InChar) NODISCARD FORCEINLINE static constexpr unsigned ToDigit(CharType 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(FCharType) > 1) if (InChar >> 8) return DigitFromChar[0]; if constexpr (sizeof(CharType) > 1) if (InChar >> 8) return DigitFromChar[0];
return DigitFromChar[InChar]; return DigitFromChar[InChar];
} }
NODISCARD FORCEINLINE static constexpr unsigned ToDigit(FCharType InChar, bool bLowercase) NODISCARD FORCEINLINE static constexpr unsigned ToDigit(CharType 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(FCharType) > 1) if (InChar >> 8) return DigitFromChar[0]; if constexpr (sizeof(CharType) > 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(FCharType) > 1) if (InChar >> 8) return DigitFromChar[0]; if constexpr (sizeof(CharType) > 1) if (InChar >> 8) return DigitFromChar[0];
return DigitFromChar[InChar]; return DigitFromChar[InChar];
} }
NODISCARD FORCEINLINE static constexpr FCharType FromDigit(unsigned InDigit) NODISCARD FORCEINLINE static constexpr CharType 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(FCharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit]; return LITERAL(CharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit];
} }
NODISCARD FORCEINLINE static constexpr FCharType FromDigit(unsigned InDigit, bool bLowercase) NODISCARD FORCEINLINE static constexpr CharType 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(FCharType, "0123456789abcdefghijklmnopqrstuvwxyz")[InDigit]; if (bLowercase) return LITERAL(CharType, "0123456789abcdefghijklmnopqrstuvwxyz")[InDigit];
return LITERAL(FCharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit]; return LITERAL(CharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit];
} }
}; };

View File

@ -264,7 +264,6 @@ 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)>>)
@ -1066,9 +1065,9 @@ struct TStringObjectFormatter
} }
} }
using FUnsignedU = TMakeUnsigned<U>; using UnsignedU = TMakeUnsigned<U>;
FUnsignedU Unsigned = static_cast<FUnsignedU>(Object); UnsignedU Unsigned = static_cast<UnsignedU>(Object);
bool bNegative = false; bool bNegative = false;
@ -1078,11 +1077,11 @@ struct TStringObjectFormatter
{ {
bNegative = true; bNegative = true;
Unsigned = static_cast<FUnsignedU>(-Unsigned); Unsigned = static_cast<UnsignedU>(-Unsigned);
} }
} }
constexpr size_t BufferSize = sizeof(FUnsignedU) * 8 + 4; constexpr size_t BufferSize = sizeof(UnsignedU) * 8 + 4;
T Buffer[BufferSize]; T Buffer[BufferSize];
@ -1112,8 +1111,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<FUnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break; case 10: do { *--Iter = static_cast<T>('0' + Unsigned % Param.Base); Unsigned = static_cast<UnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
default: do { *--Iter = TChar<T>::FromDigit(Unsigned % Param.Base, bLowercase); Unsigned = static_cast<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;
} }
} }
else else
@ -1131,12 +1130,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<FUnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break; case 10: do { *--Iter = static_cast<T>('0' + Unsigned % Param.Base); Unsigned = static_cast<UnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
default: do { *--Iter = TChar<T>::FromDigit(Unsigned % Param.Base); Unsigned = static_cast<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;
} }
} }
} }
else do { *--Iter = static_cast<T>('0' + Unsigned % 10); Unsigned = static_cast<FUnsignedU>(Unsigned / 10); } while (Unsigned != 0); else do { *--Iter = static_cast<T>('0' + Unsigned % 10); Unsigned = static_cast<UnsignedU>(Unsigned / 10); } while (Unsigned != 0);
T* DigitBegin = Iter; T* DigitBegin = Iter;
@ -1145,7 +1144,7 @@ struct TStringObjectFormatter
{ {
const size_t Padding = Param.Padding - (DigitEnd - DigitBegin); const size_t Padding = Param.Padding - (DigitEnd - DigitBegin);
if (Param.Padding < sizeof(FUnsignedU) * 8) for (size_t Index = 0; Index != Padding; ++Index) *--Iter = LITERAL(T, '0'); if (Param.Padding < sizeof(UnsignedU) * 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.
@ -1172,7 +1171,7 @@ struct TStringObjectFormatter
{ {
const size_t Padding = Param.Padding - (DigitEnd - DigitBegin); const size_t Padding = Param.Padding - (DigitEnd - DigitBegin);
if (Param.Padding > sizeof(FUnsignedU) * 8) if (Param.Padding > sizeof(UnsignedU) * 8)
{ {
Result.Reserve(Result.Num() + (DigitBegin - Iter) + Param.Padding); Result.Reserve(Result.Num() + (DigitBegin - Iter) + Param.Padding);
@ -1350,7 +1349,6 @@ 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)>>)
@ -2202,17 +2200,17 @@ struct TStringObjectParser
return TChar<T>::ToDigit(Char); return TChar<T>::ToDigit(Char);
}; };
using FUnsignedU = TMakeUnsigned<U>; using UnsignedU = 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 FUnsignedU UnsignedMaximum = static_cast<FUnsignedU>(-1); constexpr UnsignedU UnsignedMaximum = static_cast<UnsignedU>(-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;
FUnsignedU LastValue = 0; UnsignedU LastValue = 0;
FUnsignedU Unsigned = 0; UnsignedU Unsigned = 0;
if (TrimmedView.IsEmpty()) return false; if (TrimmedView.IsEmpty()) return false;
@ -2225,7 +2223,7 @@ struct TStringObjectParser
TrimmedView.RemovePrefix(1); TrimmedView.RemovePrefix(1);
Unsigned = static_cast<FUnsignedU>(Digit); Unsigned = static_cast<UnsignedU>(Digit);
while (!TrimmedView.IsEmpty()) while (!TrimmedView.IsEmpty())
{ {
@ -2237,7 +2235,7 @@ struct TStringObjectParser
LastValue = Unsigned; LastValue = Unsigned;
Unsigned = static_cast<FUnsignedU>(LastValue * Base + Digit); Unsigned = static_cast<UnsignedU>(LastValue * Base + Digit);
if (Unsigned < LastValue) return false; if (Unsigned < LastValue) return false;
} }
@ -2247,11 +2245,11 @@ struct TStringObjectParser
if constexpr (CSigned<U>) if constexpr (CSigned<U>)
{ {
// Handle overflow. // Handle overflow.
if (!bNegative && Unsigned >= static_cast<FUnsignedU>(SignedMaximum)) return false; if (!bNegative && Unsigned >= static_cast<UnsignedU>(SignedMaximum)) return false;
if ( bNegative && Unsigned >= static_cast<FUnsignedU>(SignedMinimum)) return false; if ( bNegative && Unsigned >= static_cast<UnsignedU>(SignedMinimum)) return false;
// Handle negative sign. // Handle negative sign.
if (bNegative) Unsigned = static_cast<FUnsignedU>(-Unsigned); if (bNegative) Unsigned = static_cast<UnsignedU>(-Unsigned);
} }
Object = static_cast<U>(Unsigned); Object = static_cast<U>(Unsigned);
@ -2707,14 +2705,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<FElementType> Fmt, const Ts&... Args) void TString<T, Allocator>::AppendFormat(TStringView<ElementType> 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<FElementType, true>::Do(Result, Fmt, ForwardAsTuple(Args...)); NAMESPACE_PRIVATE::TStringFormatOrParseHelper<ElementType, true>::Do(Result, Fmt, ForwardAsTuple(Args...));
Append(Result.Begin(), Result.End()); Append(Result.Begin(), Result.End());
} }
@ -2723,13 +2721,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<FElementType, false>::Do(*this, Fmt, ForwardAsTuple(Args...)); return NAMESPACE_PRIVATE::TStringFormatOrParseHelper<ElementType, 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<FElementType>::Do(*this, AsConst(Value), Invalid); NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Invalid);
} }
template <CCharType T, CAllocator<T> Allocator> template <CCharType T, CAllocator<T> Allocator>
@ -2740,13 +2738,13 @@ void TString<T, Allocator>::AppendInt(U Value, unsigned Base)
struct { unsigned Base; } Param = { Base }; struct { unsigned Base; } Param = { Base };
NAMESPACE_PRIVATE::TStringObjectFormatter<FElementType>::Do(*this, AsConst(Value), Param); NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::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<FElementType>::Do(*this, AsConst(Value), Invalid); NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::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>)
@ -2754,7 +2752,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<FElementType>::Do(*this, AsConst(Value), Param); NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::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>)
@ -2762,7 +2760,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<FElementType>::Do(*this, AsConst(Value), Param); NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Param);
} }
template <CCharType T> template <CCharType T>
@ -2770,9 +2768,9 @@ constexpr bool TStringView<T>::ToBoolAndTrim()
{ {
bool Value = false; bool Value = false;
if (!NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, Value, Invalid)) if (!NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, Value, Invalid))
{ {
if (int IntValue; NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, IntValue, Invalid)) if (int IntValue; NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, IntValue, Invalid))
{ {
Value = IntValue != 0; Value = IntValue != 0;
} }
@ -2791,7 +2789,7 @@ constexpr U TStringView<T>::ToIntAndTrim(unsigned Base)
struct { unsigned Base; } Param = { Base }; struct { unsigned Base; } Param = { Base };
NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, Value, Param); NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, Value, Param);
return Value; return Value;
} }
@ -2804,7 +2802,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<FElementType>::Do(*this, Value, Param); NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, Value, Param);
return Value; return Value;
} }

View File

@ -35,33 +35,33 @@ class TString : public TArray<T, Allocator>
{ {
private: private:
using FSuper = TArray<T, Allocator>; using Super = TArray<T, Allocator>;
public: public:
using FElementType = typename FSuper::FElementType; using ElementType = typename Super::ElementType;
using FAllocatorType = typename FSuper::FAllocatorType; using AllocatorType = typename Super::AllocatorType;
using FReference = typename FSuper:: FReference; using Reference = typename Super:: Reference;
using FConstReference = typename FSuper::FConstReference; using ConstReference = typename Super::ConstReference;
using FIterator = typename FSuper:: FIterator; using Iterator = typename Super:: Iterator;
using FConstIterator = typename FSuper::FConstIterator; using ConstIterator = typename Super::ConstIterator;
using FReverseIterator = typename FSuper:: FReverseIterator; using ReverseIterator = typename Super:: ReverseIterator;
using FConstReverseIterator = typename FSuper::FConstReverseIterator; using ConstReverseIterator = typename Super::ConstReverseIterator;
static_assert(CContiguousIterator< FIterator>); static_assert(CContiguousIterator< Iterator>);
static_assert(CContiguousIterator<FConstIterator>); static_assert(CContiguousIterator<ConstIterator>);
/** 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, FElementType InChar) : FSuper(Count, InChar) { } FORCEINLINE TString(size_t Count, ElementType InChar) : Super(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 FElementType* InPtr, size_t Count) : TString(TStringView<FElementType>(InPtr, Count)) FORCEINLINE TString(const ElementType* InPtr, size_t Count) : TString(TStringView<ElementType>(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 FElementType* InPtr) : TString(TStringView<FElementType>(InPtr)) FORCEINLINE TString(const ElementType* InPtr) : TString(TStringView<ElementType>(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<FElementType> View) : TString(View.Begin(), View.End()) { } FORCEINLINE TString(TStringView<ElementType> 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<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
FORCEINLINE TString(I First, S Last) : FSuper(MoveTemp(First), MoveTemp(Last)) { } FORCEINLINE TString(I First, S Last) : Super(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<FElementType> IL) : TString(Iteration::Begin(IL), Iteration::End(IL)) { } FORCEINLINE TString(initializer_list<ElementType> 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<FElementType>(LHS) == TStringView<FElementType>(RHS); } NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, const TString& RHS) { return TStringView<ElementType>(LHS) == TStringView<ElementType>(RHS); }
/** Compares the contents of a string and a character. */ /** Compares the contents of a string and a character. */
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, FElementType RHS) { return TStringView<FElementType>(LHS) == RHS; } NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, ElementType RHS) { return TStringView<ElementType>(LHS) == RHS; }
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, const 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==( FElementType LHS, const TString& RHS) { return LHS == TStringView<FElementType>(RHS); } NODISCARD friend FORCEINLINE bool operator==( 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); } NODISCARD friend FORCEINLINE bool operator==(const ElementType* LHS, const TString& RHS) { return LHS == TStringView<ElementType>(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<FElementType>(LHS) <=> TStringView<FElementType>(RHS); } NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, const TString& RHS) { return TStringView<ElementType>(LHS) <=> TStringView<ElementType>(RHS); }
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */ /** Compares the contents of 'LHS' and 'RHS' lexicographically. */
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, FElementType RHS) { return TStringView<FElementType>(LHS) <=> RHS; } NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, ElementType RHS) { return TStringView<ElementType>(LHS) <=> RHS; }
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, const 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<=>( FElementType LHS, const TString& RHS) { return LHS <=> TStringView<FElementType>(RHS); } NODISCARD friend FORCEINLINE auto operator<=>( 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); } NODISCARD friend FORCEINLINE auto operator<=>(const ElementType* LHS, const TString& RHS) { return LHS <=> TStringView<ElementType>(RHS); }
public: public:
/** Inserts 'InValue' before 'Index' in the string. */ /** Inserts 'InValue' before 'Index' in the string. */
FORCEINLINE FIterator Insert(size_t Index, FElementType InValue) FORCEINLINE Iterator Insert(size_t Index, ElementType 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 FIterator Insert(FConstIterator Iter, FElementType InValue) FORCEINLINE Iterator Insert(ConstIterator Iter, ElementType InValue)
{ {
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator().")); checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
return FSuper::Insert(Iter, InValue); return Super::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 FIterator Insert(size_t Index, size_t Count, FElementType InValue) FORCEINLINE Iterator Insert(size_t Index, size_t Count, ElementType 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 FIterator Insert(FConstIterator Iter, size_t Count, FElementType InValue) FORCEINLINE Iterator Insert(ConstIterator Iter, size_t Count, ElementType InValue)
{ {
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator().")); checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
return FSuper::Insert(Iter, Count, InValue); return Super::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 FIterator Insert(size_t Index, TStringView<FElementType> View) FORCEINLINE Iterator Insert(size_t Index, TStringView<ElementType> 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 FIterator Insert(FConstIterator Iter, TStringView<FElementType> View) FORCEINLINE Iterator Insert(ConstIterator Iter, TStringView<ElementType> 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<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
FORCEINLINE FIterator Insert(size_t Index, I First, S Last) FORCEINLINE Iterator 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<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
FORCEINLINE FIterator Insert(FConstIterator Iter, I First, S Last) FORCEINLINE Iterator Insert(ConstIterator 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 FSuper::Insert(Iter, MoveTemp(First), MoveTemp(Last)); return Super::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 FIterator Insert(size_t Index, initializer_list<FElementType> IL) FORCEINLINE Iterator Insert(size_t Index, initializer_list<ElementType> 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 FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL) FORCEINLINE Iterator Insert(ConstIterator Iter, initializer_list<ElementType> IL)
{ {
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator().")); checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
return FSuper::Insert(Iter, IL); return Super::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 FIterator Erase(size_t Index, bool bAllowShrinking = true) FORCEINLINE Iterator 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 FIterator Erase(FConstIterator Iter, bool bAllowShrinking = true) FORCEINLINE Iterator Erase(ConstIterator 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 FSuper::StableErase(Iter, bAllowShrinking); return Super::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 FIterator Erase(size_t Index, size_t CountToErase, bool bAllowShrinking = true) FORCEINLINE Iterator 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 FIterator Erase(FConstIterator First, FConstIterator Last, bool bAllowShrinking = true) FORCEINLINE Iterator Erase(ConstIterator First, ConstIterator 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 FSuper::StableErase(First, Last, bAllowShrinking); return Super::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, FElementType InChar) { return Append(MakeCountedConstantIterator(InChar, Count), DefaultSentinel); } TString& Append(size_t Count, ElementType 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<FElementType> View) { return Append(View.Begin(), View.End()); } FORCEINLINE TString& Append(TStringView<ElementType> 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<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, 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] = FElementType(*First++); (*this)[Index] = ElementType(*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<FElementType> IL) { return Append(Iteration::Begin(IL), Iteration::End(IL)); } FORCEINLINE TString& Append(initializer_list<ElementType> 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+=(FElementType InChar) { return Append(1, InChar); } FORCEINLINE TString& operator+=(ElementType 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<FElementType> View) { return Append(View); } FORCEINLINE TString& operator+=(TStringView<ElementType> 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<FElementType> IL) { return Append(IL); } FORCEINLINE TString& operator+=(initializer_list<ElementType> 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, FElementType RHS) { return TString(LHS).Append(1, RHS); } NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, ElementType RHS) { return TString(LHS).Append(1, RHS); }
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, const FElementType* RHS) { return TString(LHS).Append( RHS); } NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, const ElementType* RHS) { return TString(LHS).Append( RHS); }
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, TStringView<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+( FElementType LHS, const TString& RHS) { return TString(1, LHS).Append(RHS); } NODISCARD friend FORCEINLINE TString operator+( ElementType LHS, const TString& RHS) { return TString(1, LHS).Append(RHS); }
NODISCARD friend FORCEINLINE TString operator+( const FElementType* LHS, const TString& RHS) { return TString( LHS).Append(RHS); } NODISCARD friend FORCEINLINE TString operator+( const ElementType* LHS, const TString& RHS) { return TString( LHS).Append(RHS); }
NODISCARD friend FORCEINLINE TString operator+(TStringView<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); }
/** 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, FElementType RHS) { LHS.Append(1, RHS); return LHS; } NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, ElementType RHS) { LHS.Append(1, RHS); return LHS; }
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, const FElementType* RHS) { LHS.Append( RHS); return LHS; } NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, const 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, TStringView<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+(TString&& LHS, const TString<ElementType>& RHS) { LHS.Append( RHS); return LHS; }
NODISCARD friend FORCEINLINE TString operator+( FElementType LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; } NODISCARD friend FORCEINLINE TString operator+( 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+( const 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+( TStringView<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; } NODISCARD friend FORCEINLINE TString operator+(const TString<ElementType>& 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([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); }); auto Index = Find([](ElementType Char) { return !TChar<ElementType>::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([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); }); auto Index = RFind([](ElementType Char) { return !TChar<ElementType>::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(FElementType, '\0')); auto Index = Find(LITERAL(ElementType, '\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<FElementType> Prefix) const NODISCARD FORCEINLINE bool StartsWith(TStringView<ElementType> Prefix) const
{ {
return TStringView<FElementType>(*this).StartsWith(Prefix); return TStringView<ElementType>(*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(FElementType Prefix) const NODISCARD FORCEINLINE bool StartsWith(ElementType Prefix) const
{ {
return TStringView<FElementType>(*this).StartsWith(Prefix); return TStringView<ElementType>(*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<FElementType> Suffix) const NODISCARD FORCEINLINE bool EndsWith(TStringView<ElementType> Suffix) const
{ {
return TStringView<FElementType>(*this).EndsWith(Suffix); return TStringView<ElementType>(*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(FElementType Suffix) const NODISCARD FORCEINLINE bool EndsWith(ElementType Suffix) const
{ {
return TStringView<FElementType>(*this).EndsWith(Suffix); return TStringView<ElementType>(*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<FElementType> View) const NODISCARD FORCEINLINE bool Contains(TStringView<ElementType> View) const
{ {
return TStringView<FElementType>(*this).Contains(View); return TStringView<ElementType>(*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(FElementType Char) const NODISCARD FORCEINLINE bool Contains(ElementType Char) const
{ {
return TStringView<FElementType>(*this).Contains(Char); return TStringView<ElementType>(*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<FElementType> F> template <CPredicate<ElementType> F>
NODISCARD FORCEINLINE bool Contains(F&& InPredicate) const NODISCARD FORCEINLINE bool Contains(F&& InPredicate) const
{ {
return TStringView<FElementType>(*this).Contains(Forward<F>(InPredicate)); return TStringView<ElementType>(*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, FElementType InChar) FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, size_t Count, ElementType 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(FConstIterator First, FConstIterator Last, size_t Count, FElementType InChar) FORCEINLINE TString& Replace(ConstIterator First, ConstIterator Last, size_t Count, ElementType 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<FElementType> View) FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, TStringView<ElementType> 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(FConstIterator First, FConstIterator Last, TStringView<FElementType> View) FORCEINLINE TString& Replace(ConstIterator First, ConstIterator Last, TStringView<ElementType> 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<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, 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<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
TString& Replace(FConstIterator First, FConstIterator Last, I InString, S Sentinel) TString& Replace(ConstIterator First, ConstIterator 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] = FElementType(*InString++); (*this)[Index] = ElementType(*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] = FElementType(*InString++); (*this)[Index] = ElementType(*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<FElementType> IL) FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, initializer_list<ElementType> 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(FConstIterator First, FConstIterator Last, initializer_list<FElementType> IL) FORCEINLINE TString& Replace(ConstIterator First, ConstIterator Last, initializer_list<ElementType> 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<FElementType>(*this).Substr(Offset, Count); return TStringView<ElementType>(*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(FElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const FORCEINLINE size_t Copy(ElementType* 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<FElementType>(*this).Copy(Dest, Count, Offset); return TStringView<ElementType>(*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<FElementType> View, size_t Index = 0) const NODISCARD size_t Find(TStringView<ElementType> 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<FElementType>(*this).Find(View, Index); return TStringView<ElementType>(*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(FElementType Char, size_t Index = 0) const NODISCARD size_t Find(ElementType 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<FElementType>(*this).Find(Char, Index); return TStringView<ElementType>(*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<FElementType> F> template <CPredicate<ElementType> 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<FElementType>(*this).Find(Forward<F>(InPredicate), Index); return TStringView<ElementType>(*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<FElementType> View, size_t Index = INDEX_NONE) const NODISCARD size_t RFind(TStringView<ElementType> 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<FElementType>(*this).RFind(View, Index); return TStringView<ElementType>(*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(FElementType Char, size_t Index = INDEX_NONE) const NODISCARD size_t RFind(ElementType 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<FElementType>(*this).RFind(Char, Index); return TStringView<ElementType>(*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<FElementType> F> template <CPredicate<ElementType> 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<FElementType>(*this).RFind(Forward<F>(InPredicate), Index); return TStringView<ElementType>(*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<FElementType> View, size_t Index = 0) const NODISCARD FORCEINLINE size_t FindFirstOf(TStringView<ElementType> 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<FElementType>(*this).FindFirstOf(View, Index); return TStringView<ElementType>(*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(FElementType Char, size_t Index = 0) const NODISCARD FORCEINLINE size_t FindFirstOf(ElementType 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<FElementType>(*this).FindFirstOf(Char, Index); return TStringView<ElementType>(*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<FElementType> View, size_t Index = INDEX_NONE) const NODISCARD FORCEINLINE size_t FindLastOf(TStringView<ElementType> 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<FElementType>(*this).FindLastOf(View, Index); return TStringView<ElementType>(*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(FElementType Char, size_t Index = INDEX_NONE) const NODISCARD FORCEINLINE size_t FindLastOf(ElementType 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<FElementType>(*this).FindLastOf(Char, Index); return TStringView<ElementType>(*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<FElementType> View, size_t Index = 0) const NODISCARD FORCEINLINE size_t FindFirstNotOf(TStringView<ElementType> 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<FElementType>(*this).FindFirstNotOf(View, Index); return TStringView<ElementType>(*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(FElementType Char, size_t Index = 0) const NODISCARD FORCEINLINE size_t FindFirstNotOf(ElementType 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<FElementType>(*this).FindFirstNotOf(Char, Index); return TStringView<ElementType>(*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<FElementType> View, size_t Index = INDEX_NONE) const NODISCARD FORCEINLINE size_t FindLastNotOf(TStringView<ElementType> 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<FElementType>(*this).FindLastNotOf(View, Index); return TStringView<ElementType>(*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(FElementType Char, size_t Index = INDEX_NONE) const NODISCARD FORCEINLINE size_t FindLastNotOf(ElementType 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<FElementType>(*this).FindLastNotOf(Char, Index); return TStringView<ElementType>(*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<FElementType*>(this->GetData())[this->Num()] = LITERAL(FElementType, '\0'); const_cast<ElementType*>(this->GetData())[this->Num()] = LITERAL(ElementType, '\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<FElementType>(*this).IsValid(); return TStringView<ElementType>(*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<FElementType>(*this).IsASCII(); return TStringView<ElementType>(*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<FElementType>(*this).IsBoolean(); return TStringView<ElementType>(*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<FElementType>(*this).IsInteger(Base, bSigned); return TStringView<ElementType>(*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<FElementType>(*this).IsFloatingPoint(bFixed, bScientific, bSigned); return TStringView<ElementType>(*this).IsFloatingPoint(bFixed, bScientific, bSigned);
} }
public: public:
@ -1202,7 +1202,7 @@ public:
*/ */
NODISCARD FORCEINLINE bool ToBool() const NODISCARD FORCEINLINE bool ToBool() const
{ {
return TStringView<FElementType>(*this).ToBool(); return TStringView<ElementType>(*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<FElementType>(*this).template ToInt<U>(Base); return TStringView<ElementType>(*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<FElementType>(*this).template ToFloat<U>(bFixed, bScientific); return TStringView<ElementType>(*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<FElementType> View = *this; TStringView<ElementType> 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<FElementType> View = *this; TStringView<ElementType> 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<FElementType> View = *this; TStringView<ElementType> 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<FElementType> Fmt, const Ts&... Args) NODISCARD static FORCEINLINE TString Format(TStringView<ElementType> 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<FElementType> Fmt, const Ts&... Args); void AppendFormat(TStringView<ElementType> 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<FElementType> Fmt, Ts&... Args) const FORCEINLINE size_t Parse(TStringView<ElementType> 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<FElementType> Fmt, Ts&... Args) FORCEINLINE size_t ParseAndTrim(TStringView<ElementType> Fmt, Ts&... Args)
{ {
TStringView<FElementType> View = *this; TStringView<ElementType> 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<FElementType>(A)); } NODISCARD friend FORCEINLINE size_t GetTypeHash(const TString& A) { return GetTypeHash(TStringView<ElementType>(A)); }
/** Overloads the Swap algorithm for TString. */ /** Overloads the Swap algorithm for TString. */
friend FORCEINLINE void Swap(TString& A, TString& B) { Swap(static_cast<FSuper&>(A), static_cast<FSuper&>(B)); } friend FORCEINLINE void Swap(TString& A, TString& B) { Swap(static_cast<Super&>(A), static_cast<Super&>(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<FElementType, Allocator>& InString) template <CCharType T> template <typename Allocator> constexpr TStringView<T>::TStringView(const TString<ElementType, 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 FSuper = TArrayView<const T>; using Super = TArrayView<const T>;
public: public:
using FElementType = T; using ElementType = T;
using FReference = typename FSuper::FReference; using Reference = typename Super::Reference;
using FIterator = typename FSuper:: FIterator; using Iterator = typename Super::Iterator;
using FReverseIterator = typename FSuper::FReverseIterator; using ReverseIterator = typename Super::ReverseIterator;
static_assert(CContiguousIterator<FIterator>); static_assert(CContiguousIterator<Iterator>);
/** 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 FElementType(*)[]>) template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const ElementType(*)[]>)
FORCEINLINE constexpr TStringView(I InFirst, size_t InCount) : FSuper(InFirst, InCount) { } FORCEINLINE constexpr TStringView(I InFirst, size_t InCount) : Super(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 FElementType(*)[]>) template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const ElementType(*)[]>)
FORCEINLINE constexpr TStringView(I InFirst, S InLast) : FSuper(InFirst, InLast) { } FORCEINLINE constexpr TStringView(I InFirst, S InLast) : Super(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<FElementType, Allocator>& InString); FORCEINLINE constexpr TStringView(const TString<ElementType, 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 FElementType* InPtr, size_t Count) : FSuper(InPtr, Count) FORCEINLINE constexpr TStringView(const ElementType* InPtr, size_t Count) : Super(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 FElementType* InPtr) FORCEINLINE constexpr TStringView(const ElementType* 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<FElementType, char>) if constexpr (CSameAs<ElementType, char>)
{ {
Length = NAMESPACE_STD::strlen(InPtr); Length = NAMESPACE_STD::strlen(InPtr);
} }
else if constexpr (CSameAs<FElementType, wchar>) else if constexpr (CSameAs<ElementType, wchar>)
{ {
Length = NAMESPACE_STD::wcslen(InPtr); Length = NAMESPACE_STD::wcslen(InPtr);
} }
else else
{ {
while (InPtr[Length] != LITERAL(FElementType, '\0')) ++Length; while (InPtr[Length] != LITERAL(ElementType, '\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<FSuper>(LHS) == static_cast<FSuper>(RHS); } NODISCARD friend constexpr bool operator==(TStringView LHS, TStringView RHS) { return static_cast<Super>(LHS) == static_cast<Super>(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, FElementType RHS) { return LHS == TStringView(&RHS, 1); } NODISCARD friend constexpr bool operator==(TStringView LHS, ElementType RHS) { return LHS == TStringView(&RHS, 1); }
NODISCARD friend constexpr bool operator==(FElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) == RHS; } NODISCARD friend constexpr bool operator==(ElementType 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<FSuper>(LHS) <=> static_cast<FSuper>(RHS); } NODISCARD friend constexpr auto operator<=>(TStringView LHS, TStringView RHS) { return static_cast<Super>(LHS) <=> static_cast<Super>(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, FElementType RHS) { return LHS <=> TStringView(&RHS, 1); } NODISCARD friend constexpr auto operator<=>(TStringView LHS, ElementType RHS) { return LHS <=> TStringView(&RHS, 1); }
NODISCARD friend constexpr auto operator<=>(FElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) <=> RHS; } NODISCARD friend constexpr auto operator<=>(ElementType 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([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); }); auto Index = Find([](ElementType Char) { return !TChar<ElementType>::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([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); }); auto Index = RFind([](ElementType Char) { return !TChar<ElementType>::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(FElementType, '\0')); auto Index = Find(LITERAL(ElementType, '\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(FElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const FORCEINLINE constexpr size_t Copy(ElementType* 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."));
FSuper Temp = this->Subview(Offset, Count); Super 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(FElementType Prefix) const NODISCARD FORCEINLINE constexpr bool StartsWith(ElementType 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(FElementType Suffix) const NODISCARD FORCEINLINE constexpr bool EndsWith(ElementType 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(FElementType Char) const NODISCARD FORCEINLINE constexpr bool Contains(ElementType 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<FElementType> F> template <CPredicate<ElementType> 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(FElementType Char, size_t Index = 0) const NODISCARD constexpr size_t Find(ElementType 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<FElementType> F> template <CPredicate<ElementType> 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(FElementType Char, size_t Index = INDEX_NONE) const NODISCARD constexpr size_t RFind(ElementType 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<FElementType> F> template <CPredicate<ElementType> 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](FElementType Char) { return View.Contains(Char); }, Index); return Find([View](ElementType 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(FElementType Char, size_t Index = 0) const NODISCARD FORCEINLINE constexpr size_t FindFirstOf(ElementType 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](FElementType Char) { return View.Contains(Char); }, Index); return RFind([View](ElementType 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(FElementType Char, size_t Index = INDEX_NONE) const NODISCARD FORCEINLINE constexpr size_t FindLastOf(ElementType 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](FElementType Char) { return !View.Contains(Char); }, Index); return Find([View](ElementType 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(FElementType Char, size_t Index = 0) const NODISCARD FORCEINLINE constexpr size_t FindFirstNotOf(ElementType Char, size_t Index = 0) const
{ {
return Find([Char](FElementType C) { return C != Char; }, Index); return Find([Char](ElementType 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](FElementType Char) { return !View.Contains(Char); }, Index); return RFind([View](ElementType 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(FElementType Char, size_t Index = INDEX_NONE) const NODISCARD FORCEINLINE constexpr size_t FindLastNotOf(ElementType Char, size_t Index = INDEX_NONE) const
{ {
return RFind([Char](FElementType C) { return C != Char; }, Index); return RFind([Char](ElementType 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(FElementType, '\0') || Contains(LITERAL(FElementType, '\0'))) if (this->Back() == LITERAL(ElementType, '\0') || Contains(LITERAL(ElementType, '\0')))
{ {
return NAMESPACE_PRIVATE::TCStringFromTStringView<FElementType>(this->GetData(), false); return NAMESPACE_PRIVATE::TCStringFromTStringView<ElementType>(this->GetData(), false);
} }
FElementType* Buffer = new FElementType[this->Num() + 1]; ElementType* Buffer = new ElementType[this->Num() + 1];
Copy(Buffer); Copy(Buffer);
Buffer[this->Num()] = LITERAL(FElementType, '\0'); Buffer[this->Num()] = LITERAL(ElementType, '\0');
return NAMESPACE_PRIVATE::TCStringFromTStringView<FElementType>(Buffer, true); return NAMESPACE_PRIVATE::TCStringFromTStringView<ElementType>(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 (FElementType Char : *this) for (ElementType Char : *this)
{ {
if (!TChar<FElementType>::IsValid(Char)) return false; if (!TChar<ElementType>::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 (FElementType Char : *this) for (ElementType Char : *this)
{ {
if (!TChar<FElementType>::IsASCII(Char)) return false; if (!TChar<ElementType>::IsASCII(Char)) return false;
} }
return true; return true;
@ -543,7 +543,7 @@ public:
{ {
TStringView View = *this; TStringView View = *this;
if (View.StartsWith(LITERAL(FElementType, '-'))) if (View.StartsWith(LITERAL(ElementType, '-')))
{ {
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(FElementType, '-'))) if (View.StartsWith(LITERAL(ElementType, '-')))
{ {
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<FSuper>(A)); } NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(TStringView A) { return GetTypeHash(static_cast<Super>(A)); }
}; };
@ -676,8 +676,6 @@ 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))
@ -687,8 +685,6 @@ 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 FDecayedType = TDecay<T>; using DecayedType = TDecay<T>;
if constexpr (CAssignableFrom<FDecayedType, T&&>) if constexpr (CAssignableFrom<DecayedType, T&&>)
{ {
if (HoldsAlternative<FDecayedType>()) if (HoldsAlternative<DecayedType>())
{ {
GetValue<FDecayedType>() = Forward<T>(InValue); GetValue<DecayedType>() = Forward<T>(InValue);
return *this; return *this;
} }
} }
Destroy(); Destroy();
EmplaceImpl<FDecayedType>(Forward<T>(InValue)); EmplaceImpl<DecayedType>(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 FDecayedType = TDecay<T>; using DecayedType = TDecay<T>;
TypeInfo = reinterpret_cast<uintptr>(&typeid(FDecayedType)); TypeInfo = reinterpret_cast<uintptr>(&typeid(DecayedType));
if constexpr (CEmpty<FDecayedType> && CTrivial<FDecayedType>) return; // ERepresentation::Empty if constexpr (CEmpty<DecayedType> && CTrivial<DecayedType>) return; // ERepresentation::Empty
constexpr bool bIsTriviallyStorable = sizeof(FDecayedType) <= sizeof(TrivialStorage.Internal) && alignof(FDecayedType) <= alignof(FAny) && CTriviallyCopyable<FDecayedType>; constexpr bool bIsTriviallyStorable = sizeof(DecayedType) <= sizeof(TrivialStorage.Internal) && alignof(DecayedType) <= alignof(FAny) && CTriviallyCopyable<DecayedType>;
constexpr bool bIsSmallStorable = sizeof(FDecayedType) <= sizeof( SmallStorage.Internal) && alignof(FDecayedType) <= alignof(FAny); constexpr bool bIsSmallStorable = sizeof(DecayedType) <= sizeof( SmallStorage.Internal) && alignof(DecayedType) <= alignof(FAny);
static constexpr const FRTTI SelectedRTTI(InPlaceType<FDecayedType>); static constexpr const FRTTI SelectedRTTI(InPlaceType<DecayedType>);
if constexpr (bIsTriviallyStorable) if constexpr (bIsTriviallyStorable)
{ {
new (&TrivialStorage.Internal) FDecayedType(Forward<Ts>(Args)...); new (&TrivialStorage.Internal) DecayedType(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) FDecayedType(Forward<Ts>(Args)...); new (&SmallStorage.Internal) DecayedType(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(FDecayedType), alignof(FDecayedType)); BigStorage.External = Memory::Malloc(sizeof(DecayedType), alignof(DecayedType));
new (BigStorage.External) FDecayedType(Forward<Ts>(Args)...); new (BigStorage.External) DecayedType(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 FNativeAtomic = TConditional<bIsRef, NAMESPACE_STD::atomic_ref<T>, NAMESPACE_STD::atomic<T>>; using NativeAtomicType = TConditional<bIsRef, NAMESPACE_STD::atomic_ref<T>, NAMESPACE_STD::atomic<T>>;
public: public:
using FValueType = T; using ValueType = T;
/** Indicates that the type is always lock-free */ /** Indicates that the type is always lock-free */
static constexpr bool bIsAlwaysLockFree = FNativeAtomic::is_always_lock_free; static constexpr bool bIsAlwaysLockFree = NativeAtomicType::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(FValueType Desired) requires (!bIsRef) : NativeAtomic(Desired) { } FORCEINLINE constexpr TAtomicImpl(ValueType Desired) requires (!bIsRef) : NativeAtomic(Desired) { };
/** Constructs an atomic reference. */ /** Constructs an atomic reference. */
FORCEINLINE explicit TAtomicImpl(FValueType& Desired) requires (bIsRef) : NativeAtomic(Desired) { check(Memory::IsAligned(&Desired, RequiredAlignment)); } FORCEINLINE explicit TAtomicImpl(ValueType& 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 FValueType operator=(FValueType Desired) { return NativeAtomic = Desired; } FORCEINLINE ValueType operator=(ValueType Desired) { return NativeAtomic = Desired; }
FORCEINLINE FValueType operator=(FValueType Desired) volatile requires (bIsAlwaysLockFree) { return NativeAtomic = Desired; } FORCEINLINE ValueType operator=(ValueType 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(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) { 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)); } 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)); }
/** Atomically obtains the value of the atomic object. */ /** Atomically obtains the value of the atomic object. */
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 { 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)); } 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)); }
/** Loads a value from an atomic object. */ /** Loads a value from an atomic object. */
NODISCARD FORCEINLINE operator FValueType() const { return static_cast<FValueType>(NativeAtomic); } NODISCARD FORCEINLINE operator ValueType() const { return static_cast<ValueType>(NativeAtomic); }
NODISCARD FORCEINLINE operator FValueType() const volatile requires (bIsAlwaysLockFree) { return static_cast<FValueType>(NativeAtomic); } NODISCARD FORCEINLINE operator ValueType() const volatile requires (bIsAlwaysLockFree) { return static_cast<ValueType>(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 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) { 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)); } NODISCARD FORCEINLINE ValueType Exchange(ValueType 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(FValueType& Expected, FValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false) NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType 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(FValueType& Expected, FValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree) NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType 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(FValueType& Expected, FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false) NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType 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(FValueType& Expected, FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree) NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType 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(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) { 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)); } 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)); }
/** 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<FValueType, F, FValueType>) template <typename F> requires (CInvocableResult<ValueType, F, ValueType>)
FORCEINLINE FValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent)
{ {
FValueType Temp(Load(EMemoryOrder::Relaxed)); ValueType 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<FValueType>(Forward<F>(Func), Temp), Order, true)); while (!CompareExchange(Temp, InvokeResult<ValueType>(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<FValueType, F, FValueType> && bIsAlwaysLockFree) template <typename F> requires (CInvocableResult<ValueType, F, ValueType> && bIsAlwaysLockFree)
FORCEINLINE FValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile
{ {
FValueType Temp(Load(EMemoryOrder::Relaxed)); ValueType 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<FValueType>(Forward<F>(Func), Temp), Order, true)); while (!CompareExchange(Temp, InvokeResult<ValueType>(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 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) requires (CIntegral<T> || CFloatingPoint<T>) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchAdd(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); } 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)); }
/** 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 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) requires (CPointer<T> ) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); } 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)); }
/** 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 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) requires (CIntegral<T> || CFloatingPoint<T>) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchSub(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); } 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)); }
/** 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 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) requires (CPointer<T> ) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); } 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)); }
/** 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 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) requires (CIntegral<T> || CFloatingPoint<T>) { 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; }); } 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; }); }
/** 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 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) requires (CIntegral<T> || CFloatingPoint<T>) { 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; }); } 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; }); }
/** 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 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) requires (CIntegral<T> ) { 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; }); } FORCEINLINE ValueType FetchMod(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { 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 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) requires (CIntegral<T> ) { return NativeAtomic.fetch_and(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchAnd(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_and(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); } 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)); }
/** 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 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) requires (CIntegral<T> ) { return NativeAtomic.fetch_or(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchOr(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_or(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); } 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)); }
/** 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 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) requires (CIntegral<T> ) { return NativeAtomic.fetch_xor(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
FORCEINLINE FValueType FetchXor(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_xor(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); } 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)); }
/** 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 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) requires (CIntegral<T> ) { 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; }); } FORCEINLINE ValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { 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 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) requires (CIntegral<T> ) { 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; }); } FORCEINLINE ValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old >> InValue; }); }
/** Increments the atomic value by one. */
FORCEINLINE ValueType operator++() requires ((CIntegral<T> || CPointer<T>) ) { return ++NativeAtomic; }
FORCEINLINE ValueType operator++() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return ++NativeAtomic; }
/** Increments the atomic value by one. */ /** Increments the atomic value by one. */
FORCEINLINE FValueType operator++() requires ((CIntegral<T> || CPointer<T>) ) { return ++NativeAtomic; } FORCEINLINE ValueType operator++(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic++; }
FORCEINLINE FValueType operator++() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return ++NativeAtomic; } FORCEINLINE ValueType operator++(int) 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 FValueType operator--() requires ((CIntegral<T> || CPointer<T>) ) { return --NativeAtomic; } FORCEINLINE ValueType operator--() requires ((CIntegral<T> || CPointer<T>) ) { return --NativeAtomic; }
FORCEINLINE FValueType operator--() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return --NativeAtomic; } FORCEINLINE ValueType operator--() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return --NativeAtomic; }
/** Decrements the atomic value by one. */ /** Decrements the atomic value by one. */
FORCEINLINE FValueType operator--(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic--; } FORCEINLINE ValueType operator--(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic--; }
FORCEINLINE FValueType operator--(int) volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return NativeAtomic--; } FORCEINLINE ValueType operator--(int) volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return NativeAtomic--; }
/** Adds with the atomic value. */
FORCEINLINE ValueType operator+=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic += InValue; }
FORCEINLINE ValueType operator+=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic += InValue; }
/** Adds with the atomic value. */ /** Adds with the atomic value. */
FORCEINLINE FValueType operator+=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic += InValue; } FORCEINLINE ValueType operator+=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic += InValue; }
FORCEINLINE FValueType operator+=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic += InValue; } FORCEINLINE ValueType operator+=(ptrdiff InValue) volatile requires (CPointer<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 FValueType operator-=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic -= InValue; } FORCEINLINE ValueType operator-=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic -= InValue; }
FORCEINLINE FValueType operator-=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic -= InValue; } FORCEINLINE ValueType operator-=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
/** Subtracts with the atomic value. */ /** Subtracts with the atomic value. */
FORCEINLINE FValueType operator-=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic -= InValue; } FORCEINLINE ValueType operator-=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic -= InValue; }
FORCEINLINE FValueType operator-=(ptrdiff InValue) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic -= InValue; } FORCEINLINE ValueType operator-=(ptrdiff InValue) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
/** Multiples with the atomic value. */ /** Multiples with the atomic value. */
FORCEINLINE FValueType operator*=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchMul(InValue) * InValue; } FORCEINLINE ValueType operator*=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchMul(InValue) * InValue; }
FORCEINLINE FValueType operator*=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchMul(InValue) * InValue; } FORCEINLINE ValueType operator*=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchMul(InValue) * InValue; }
/** Divides with the atomic value. */ /** Divides with the atomic value. */
FORCEINLINE FValueType operator/=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchDiv(InValue) / InValue; } FORCEINLINE ValueType operator/=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchDiv(InValue) / InValue; }
FORCEINLINE FValueType operator/=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchDiv(InValue) / InValue; } FORCEINLINE ValueType operator/=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchDiv(InValue) / InValue; }
/** Models with the atomic value. */ /** Models with the atomic value. */
FORCEINLINE FValueType operator%=(FValueType InValue) requires (CIntegral<T> ) { return FetchMod(InValue) % InValue; } FORCEINLINE ValueType operator%=(ValueType InValue) requires (CIntegral<T> ) { return FetchMod(InValue) % InValue; }
FORCEINLINE FValueType operator%=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchMod(InValue) % InValue; } FORCEINLINE ValueType operator%=(ValueType 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 FValueType operator&=(FValueType InValue) requires (CIntegral<T> ) { return NativeAtomic &= InValue; } FORCEINLINE ValueType operator&=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic &= InValue; }
FORCEINLINE FValueType operator&=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic &= InValue; } FORCEINLINE ValueType operator&=(ValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic &= InValue; }
/** Performs bitwise OR with the atomic value. */ /** Performs bitwise OR with the atomic value. */
FORCEINLINE FValueType operator|=(FValueType InValue) requires (CIntegral<T> ) { return NativeAtomic |= InValue; } FORCEINLINE ValueType operator|=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic |= InValue; }
FORCEINLINE FValueType operator|=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic |= InValue; } FORCEINLINE ValueType operator|=(ValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic |= InValue; }
/** Performs bitwise XOR with the atomic value. */ /** Performs bitwise XOR with the atomic value. */
FORCEINLINE FValueType operator^=(FValueType InValue) requires (CIntegral<T> ) { return NativeAtomic ^= InValue; } FORCEINLINE ValueType operator^=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic ^= InValue; }
FORCEINLINE FValueType operator^=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic ^= InValue; } FORCEINLINE ValueType operator^=(ValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic ^= InValue; }
/** Performs bitwise LSH with the atomic value. */ /** Performs bitwise LSH with the atomic value. */
FORCEINLINE FValueType operator<<=(size_t InValue) requires (CIntegral<T> ) { return FetchLsh(InValue) << InValue; } FORCEINLINE ValueType operator<<=(size_t InValue) requires (CIntegral<T> ) { return FetchLsh(InValue) << InValue; }
FORCEINLINE FValueType operator<<=(size_t InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchLsh(InValue) << InValue; } FORCEINLINE ValueType 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 FValueType operator>>=(size_t InValue) requires (CIntegral<T> ) { return FetchRsh(InValue) >> InValue; } FORCEINLINE ValueType operator>>=(size_t InValue) requires (CIntegral<T> ) { return FetchRsh(InValue) >> InValue; }
FORCEINLINE FValueType operator>>=(size_t InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchRsh(InValue) >> InValue; } FORCEINLINE ValueType operator>>=(size_t InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchRsh(InValue) >> InValue; }
protected: protected:
FNativeAtomic NativeAtomic; NativeAtomicType NativeAtomic;
}; };
@ -311,7 +311,7 @@ struct FAtomicFlag final : FSingleton
public: public:
/** Constructs an atomic flag. */ /** Constructs an atomic flag. */
FORCEINLINE constexpr FAtomicFlag() = default; FORCEINLINE constexpr FAtomicFlag() : NativeAtomic() { };
/** 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 FDecayedType = TDecay<T>; using DecayedType = TDecay<T>;
static constexpr const FRTTI SelectedRTTI(InPlaceType<FDecayedType>); static constexpr const FRTTI SelectedRTTI(InPlaceType<DecayedType>);
RTTI = reinterpret_cast<uintptr>(&SelectedRTTI); RTTI = reinterpret_cast<uintptr>(&SelectedRTTI);
if constexpr (CEmpty<FDecayedType> && CTrivial<FDecayedType>) return; // ERepresentation::Empty if constexpr (CEmpty<DecayedType> && CTrivial<DecayedType>) return; // ERepresentation::Empty
constexpr bool bIsTriviallyStorable = sizeof(FDecayedType) <= sizeof(InternalStorage) && alignof(FDecayedType) <= alignof(TFunctionStorage) && CTriviallyCopyable<FDecayedType>; constexpr bool bIsTriviallyStorable = sizeof(DecayedType) <= sizeof(InternalStorage) && alignof(DecayedType) <= alignof(TFunctionStorage) && CTriviallyCopyable<DecayedType>;
constexpr bool bIsSmallStorable = sizeof(FDecayedType) <= sizeof(InternalStorage) && alignof(FDecayedType) <= alignof(TFunctionStorage); constexpr bool bIsSmallStorable = sizeof(DecayedType) <= sizeof(InternalStorage) && alignof(DecayedType) <= alignof(TFunctionStorage);
if constexpr (bIsTriviallyStorable) if constexpr (bIsTriviallyStorable)
{ {
new (&InternalStorage) FDecayedType(Forward<Ts>(Args)...); new (&InternalStorage) DecayedType(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) FDecayedType(Forward<Ts>(Args)...); new (&InternalStorage) DecayedType(Forward<Ts>(Args)...);
RTTI |= static_cast<uintptr>(ERepresentation::Small); RTTI |= static_cast<uintptr>(ERepresentation::Small);
} }
else else
{ {
ExternalStorage = new FDecayedType(Forward<Ts>(Args)...); ExternalStorage = new DecayedType(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 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...) && > { using Fn = Ret(Ts...); using CVRef = 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 Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const&&> { using Fn = Ret(Ts...); using CVRef = 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 FResultType = Ret; using ResultType = Ret;
using FArgumentType = TTypeSequence<Ts...>; using ArgumentType = 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 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) && requires (CSameAs<CVRef, int&&>) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE FResultType operator()(Ts... Args) const requires (CSameAs<CVRef, const int >) { return CallImpl(Forward<Ts>(Args)...); } FORCEINLINE 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)...); }
/** @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 FCallableType = FResultType(*)(uintptr, Ts&&...); using CallableType = ResultType(*)(uintptr, Ts&&...);
TFunctionStorage<bIsRef, bIsUnique> Storage; TFunctionStorage<bIsRef, bIsUnique> Storage;
FORCEINLINE FResultType CallImpl(Ts&&... Args) const FORCEINLINE ResultType CallImpl(Ts&&... Args) const
{ {
checkf(Storage.IsValid(), TEXT("Attempting to call an unbound TFunction!")); checkf(Storage.IsValid(), TEXT("Attempting to call an unbound TFunction!"));
FCallableType Callable = reinterpret_cast<FCallableType>(Storage.GetCallable()); CallableType Callable = reinterpret_cast<CallableType>(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 FDecayedType = TDecay<T>; using DecayedType = 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 FObjectType = TCopyCVRef<CVRef, FDecayedType>; using ObjectType = TCopyCVRef<CVRef, DecayedType>;
using FInvokeType = TConditional<CReference<FObjectType>, FObjectType, FObjectType&>; using InvokeType = TConditional<CReference<ObjectType>, ObjectType, ObjectType&>;
FCallableType Callable = [](uintptr ObjectPtr, Ts&&... Args) -> FResultType CallableType Callable = [](uintptr ObjectPtr, Ts&&... Args) -> ResultType
{ {
return InvokeResult<FResultType>( return InvokeResult<ResultType>(
static_cast<FInvokeType>(*reinterpret_cast<FDecayedType*>(ObjectPtr)), static_cast<InvokeType>(*reinterpret_cast<DecayedType*>(ObjectPtr)),
Forward<Ts>(Args)... Forward<Ts>(Args)...
); );
}; };
Storage.template Emplace<FDecayedType>( Storage.template Emplace<DecayedType>(
reinterpret_cast<uintptr>(Callable), reinterpret_cast<uintptr>(Callable),
Forward<Us>(Args)... Forward<Us>(Args)...
); );
return *reinterpret_cast<FDecayedType*>(Storage.GetValuePtr()); return *reinterpret_cast<DecayedType*>(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>::FFn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
true> true>
{ {
private: private:
using FImpl = NAMESPACE_PRIVATE::TFunctionImpl< using Impl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
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"));
FImpl::template Emplace<T>(Forward<T>(InValue)); Impl::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>::FFn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
false, false> false, false>
{ {
private: private:
using FImpl = NAMESPACE_PRIVATE::TFunctionImpl< using Impl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
false, false>; false, false>;
public: public:
/** Default constructor. */ /** Default constructor. */
FORCEINLINE constexpr TFunction(nullptr_t = nullptr) { FImpl::Invalidate(); } FORCEINLINE constexpr TFunction(nullptr_t = nullptr) { Impl::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)) FImpl::Invalidate(); if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Impl::Invalidate();
else FImpl::template Emplace<T>(Forward<T>(InValue)); else Impl::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)
{ {
FImpl::template Emplace<T>(Forward<Ts>(Args)...); Impl::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)
{ {
FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...); Impl::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)
{ {
FImpl::Destroy(); Impl::Destroy();
return FImpl::template Emplace<T>(Forward<Ts>(Args)...); return Impl::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)
{ {
FImpl::Destroy(); Impl::Destroy();
return FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...); return Impl::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() { FImpl::Destroy(); FImpl::Invalidate(); } FORCEINLINE constexpr void Reset() { Impl::Destroy(); Impl::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<FImpl&>(A), static_cast<FImpl&>(B)); } friend FORCEINLINE constexpr void Swap(TFunction& A, TFunction& B) { Swap(static_cast<Impl&>(A), static_cast<Impl&>(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>::FFn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
false, true> false, true>
{ {
private: private:
using FImpl = NAMESPACE_PRIVATE::TFunctionImpl< using Impl = NAMESPACE_PRIVATE::TFunctionImpl<
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef, typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
false, true>; false, true>;
public: public:
/** Default constructor. */ /** Default constructor. */
FORCEINLINE constexpr TUniqueFunction(nullptr_t = nullptr) { FImpl::Invalidate(); } FORCEINLINE constexpr TUniqueFunction(nullptr_t = nullptr) { Impl::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)) FImpl::Invalidate(); if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Impl::Invalidate();
else FImpl::template Emplace<T>(Forward<T>(InValue)); else Impl::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)
{ {
FImpl::template Emplace<T>(Forward<Ts>(Args)...); Impl::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)
{ {
FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...); Impl::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) { FImpl::Destroy(); FImpl::Invalidate(); return *this; } FORCEINLINE constexpr TUniqueFunction& operator=(nullptr_t) { Impl::Destroy(); Impl::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)
{ {
FImpl::Destroy(); Impl::Destroy();
using DecayedType = TDecay<T>;
return FImpl::template Emplace<T>(Forward<Ts>(Args)...); return Impl::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)
{ {
FImpl::Destroy(); Impl::Destroy();
using DecayedType = TDecay<T>;
return FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...); return Impl::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() { FImpl::Destroy(); FImpl::Invalidate(); } FORCEINLINE constexpr void Reset() { Impl::Destroy(); Impl::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<FImpl&>(A), static_cast<FImpl&>(B)); } friend FORCEINLINE constexpr void Swap(TUniqueFunction& A, TUniqueFunction& B) { Swap(static_cast<Impl&>(A), static_cast<Impl&>(B)); }
}; };

View File

@ -10,7 +10,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_PRIVATE_BEGIN NAMESPACE_PRIVATE_BEGIN
struct FInvokeFunction struct InvokeFunction
{ {
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 FInvokeFunction
} }
}; };
struct FInvokeMemberFunction struct InvokeMemberFunction
{ {
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 FInvokeMemberFunction
} }
}; };
struct FInvokeMemberObject struct InvokeMemberObject
{ {
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 FInvokeMember; struct InvokeMember;
template <typename F, typename T, typename Decayed> template <typename F, typename T, typename Decayed>
struct FInvokeMember<F, T, Decayed, true, false> : FInvokeMemberFunction { }; struct InvokeMember<F, T, Decayed, true, false> : InvokeMemberFunction { };
template <typename F, typename T, typename Decayed> template <typename F, typename T, typename Decayed>
struct FInvokeMember<F, T, Decayed, false, true> : FInvokeMemberObject { }; struct InvokeMember<F, T, Decayed, false, true> : InvokeMemberObject { };
template <typename F, typename T, typename Decayed> template <typename F, typename T, typename Decayed>
struct FInvokeMember<F, T, Decayed, false, false> : FInvokeFunction { }; struct InvokeMember<F, T, Decayed, false, false> : InvokeFunction { };
template <typename F, typename... Ts> template <typename F, typename... Ts>
struct FInvokeImpl; struct InvokeImpl;
template <typename F> template <typename F>
struct FInvokeImpl<F> : FInvokeFunction { }; struct InvokeImpl<F> : InvokeFunction { };
template <typename F, typename T, typename... Ts> template <typename F, typename T, typename... Ts>
struct FInvokeImpl<F, T, Ts...> : FInvokeMember<F, T> { }; struct InvokeImpl<F, T, Ts...> : InvokeMember<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::FInvokeImpl<F, Ts...>::Invoke(Forward<F>(Func), Forward<Ts>(Args)...)) -> decltype(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)...); return NAMESPACE_PRIVATE::InvokeImpl<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 FValueType = T; using ValueType = 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 FType = typename __make_integer_seq<TIntegerSequence, T, N>; using Type = 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 FType = typename __make_integer_seq<TIntegerSequence, T, N>; using Type = 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 FType = typename TMakeIntegerSequenceImpl<N - 1, T, T(N - 1), Ints...>::FType; using Type = typename TMakeIntegerSequenceImpl<N - 1, T, T(N - 1), Ints...>::Type;
}; };
template <typename T, T... Ints> template <typename T, T... Ints>
struct TMakeIntegerSequenceImpl<0, T, Ints...> struct TMakeIntegerSequenceImpl<0, T, Ints...>
{ {
using FType = TIntegerSequence<T, Ints...>; using Type = 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>::FType; using TMakeIntegerSequence = typename NAMESPACE_PRIVATE::TMakeIntegerSequenceImpl<N, T>::Type;
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 FType = T; using Type = 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 FType = TTypeSequence<Ts...>; using Type = 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 FType = TTypeSequence<T, Ts...>; using Type = TTypeSequence<T, Ts...>;
}; };
NAMESPACE_PRIVATE_END NAMESPACE_PRIVATE_END
template <CTTypeSequence TSequence> template <CTTypeSequence TSequence>
using TFront = typename NAMESPACE_PRIVATE::TFrontImpl<TSequence>::FType; using TFront = typename NAMESPACE_PRIVATE::TFrontImpl<TSequence>::Type;
template <CTTypeSequence TSequence> template <CTTypeSequence TSequence>
using TPop = typename NAMESPACE_PRIVATE::TPopImpl<TSequence>::FType; using TPop = typename NAMESPACE_PRIVATE::TPopImpl<TSequence>::Type;
template <typename T, typename TSequence> template <typename T, typename TSequence>
using TPush = typename NAMESPACE_PRIVATE::TPushImpl<T, TSequence>::FType; using TPush = typename NAMESPACE_PRIVATE::TPushImpl<T, TSequence>::Type;
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 FType = typename TTypeImpl<I - 1, TPop<TSequence>>::FType; using Type = typename TTypeImpl<I - 1, TPop<TSequence>>::Type;
}; };
template <typename TSequence> template <typename TSequence>
struct TTypeImpl<0, TSequence> struct TTypeImpl<0, TSequence>
{ {
using FType = TFront<TSequence>; using Type = TFront<TSequence>;
}; };
template <typename TSequence> template <typename TSequence>
struct TTypeImpl<INDEX_NONE, TSequence> struct TTypeImpl<INDEX_NONE, TSequence>
{ {
using FType = void; using Type = 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 FType = TCopyCV<TSequence, typename TTypeImpl<SafeIndex, TSequence>::FType>; using Type = TCopyCV<TSequence, typename TTypeImpl<SafeIndex, TSequence>::Type>;
}; };
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>::FType; using TType = typename NAMESPACE_PRIVATE::TTypeAssert<I, TSequence>::Type;
NAMESPACE_PRIVATE_BEGIN NAMESPACE_PRIVATE_BEGIN
template <typename TSequence> template <typename TSequence>
struct TUniqueTypeSequenceImpl struct TUniqueTypeSequenceImpl
{ {
using FFrontType = TFront<TSequence>; using FrontType = TFront<TSequence>;
using FNextSequence = TPop<TSequence>; using NextSequence = TPop<TSequence>;
using FNextUniqueSequence = typename TUniqueTypeSequenceImpl<FNextSequence>::FType; using NextUniqueSequence = typename TUniqueTypeSequenceImpl<NextSequence>::Type;
using FType = TConditional<!CExistentType<FFrontType, FNextSequence>, TPush<FFrontType, FNextUniqueSequence>, FNextUniqueSequence>; using Type = TConditional<!CExistentType<FrontType, NextSequence>, TPush<FrontType, NextUniqueSequence>, NextUniqueSequence>;
}; };
template <> template <>
struct TUniqueTypeSequenceImpl<TTypeSequence<>> struct TUniqueTypeSequenceImpl<TTypeSequence<>>
{ {
using FType = TTypeSequence<>; using Type = TTypeSequence<>;
}; };
NAMESPACE_PRIVATE_END NAMESPACE_PRIVATE_END
template <CTTypeSequence TSequence> template <CTTypeSequence TSequence>
using TUniqueTypeSequence = typename NAMESPACE_PRIVATE::TUniqueTypeSequenceImpl<TSequence>::FType; using TUniqueTypeSequence = typename NAMESPACE_PRIVATE::TUniqueTypeSequenceImpl<TSequence>::Type;
NAMESPACE_PRIVATE_BEGIN NAMESPACE_PRIVATE_BEGIN

View File

@ -45,9 +45,9 @@ class TOptional<T, false> final
{ {
public: public:
using FValueType = T; using ValueType = T;
static_assert(!CReference<FValueType>); static_assert(!CReference<ValueType>);
/** 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) FValueType(Forward<Ts>(Args)...); new (&Value) ValueType(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) FValueType(IL, Forward<Ts>(Args)...); new (&Value) ValueType(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) FValueType(InValue.GetValue()); if (InValue.IsValid()) new (&Value) ValueType(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) FValueType(MoveTemp(InValue.GetValue())); if (InValue.IsValid()) new (&Value) ValueType(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) FValueType(InValue.GetValue()); if (InValue.IsValid()) new (&Value) ValueType(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) FValueType(MoveTemp(InValue.GetValue())); if (InValue.IsValid()) new (&Value) ValueType(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) FValueType(InValue.GetValue()); new (&Value) ValueType(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) FValueType(MoveTemp(InValue.GetValue())); new (&Value) ValueType(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) FValueType(InValue.GetValue()); new (&Value) ValueType(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) FValueType(MoveTemp(InValue.GetValue())); new (&Value) ValueType(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) FValueType(Forward<U>(InValue)); new (&Value) ValueType(Forward<U>(InValue));
bIsValid = true; bIsValid = true;
} }
@ -278,7 +278,7 @@ public:
{ {
Reset(); Reset();
T* Result = new (&Value) FValueType(Forward<Ts>(Args)...); T* Result = new (&Value) ValueType(Forward<Ts>(Args)...);
bIsValid = true; bIsValid = true;
return *Result; return *Result;
@ -298,7 +298,7 @@ public:
{ {
Reset(); Reset();
T* Result = new (&Value) FValueType(IL, Forward<Ts>(Args)...); T* Result = new (&Value) ValueType(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)->~FValueType(); reinterpret_cast<T*>(&Value)->~ValueType();
} }
} }
@ -380,9 +380,9 @@ class TOptional<T, true> final
{ {
public: public:
using FValueType = TRemoveReference<T>; using ValueType = TRemoveReference<T>;
static_assert(!CReference<FValueType>); static_assert(!CReference<ValueType>);
/** 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<FValueType> && CConstructibleFrom<T, U&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<U, T>) template <typename U> requires (!CConst<ValueType> && 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<FValueType> && CConstructibleFrom<T, const U&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<U, T>) template <typename U> requires (CConst<ValueType> && 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:
FValueType* Ptr; ValueType* 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 FElementType = TPointerTraits<T>::FElementType; using ElementType = TPointerTraits<T>::ElementType;
/** 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 FElementType* Get() { return TPointerTraits<T>::ToAddress(Ptr); } NODISCARD FORCEINLINE constexpr ElementType* Get() { return TPointerTraits<T>::ToAddress(Ptr); }
NODISCARD FORCEINLINE constexpr const FElementType* Get() const { return TPointerTraits<T>::ToAddress(Ptr); } NODISCARD FORCEINLINE constexpr const ElementType* Get() const { return TPointerTraits<T>::ToAddress(Ptr); }
/** @return true if *this owns an object, false otherwise. */ /** @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 FElementType& operator*() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); } NODISCARD FORCEINLINE constexpr ElementType& operator*() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); }
NODISCARD FORCEINLINE constexpr const FElementType& operator*() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); } NODISCARD FORCEINLINE constexpr const ElementType& operator*() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); }
NODISCARD FORCEINLINE constexpr FElementType* operator->() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); } NODISCARD FORCEINLINE constexpr ElementType* operator->() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); }
NODISCARD FORCEINLINE constexpr const FElementType* operator->() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); } NODISCARD FORCEINLINE constexpr const ElementType* 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 FElementType*() requires (CConvertibleTo<T, FElementType*>) { return Ptr; } NODISCARD FORCEINLINE constexpr operator ElementType*() requires (CConvertibleTo<T, ElementType*>) { return Ptr; }
NODISCARD FORCEINLINE constexpr operator const FElementType*() const requires (CConvertibleTo<T, FElementType*>) { return Ptr; } NODISCARD FORCEINLINE constexpr operator const ElementType*() const requires (CConvertibleTo<T, ElementType*>) { 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 FType = ReferencedType; using Type = 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 FType = T; }; template <typename T> struct TUnwrapReferenceImpl { using Type = T; };
template <typename T> struct TUnwrapReferenceImpl<TReferenceWrapper<T>> { using FType = T&; }; template <typename T> struct TUnwrapReferenceImpl<TReferenceWrapper<T>> { using Type = T&; };
template <typename T> struct TUnwrapRefDecayImpl { using FType = typename TUnwrapReferenceImpl<TDecay<T>>::FType; }; template <typename T> struct TUnwrapRefDecayImpl { using Type = typename TUnwrapReferenceImpl<TDecay<T>>::Type; };
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>::FType; using TUnwrapReference = typename NAMESPACE_PRIVATE::TUnwrapReferenceImpl<T>::Type;
template <typename T> template <typename T>
using TUnwrapRefDecay = typename NAMESPACE_PRIVATE::TUnwrapRefDecayImpl<T>::FType; using TUnwrapRefDecay = typename NAMESPACE_PRIVATE::TUnwrapRefDecayImpl<T>::Type;
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 FType = Meta::TType<I, TTypeSequence<Ts...>>; using Type = Meta::TType<I, TTypeSequence<Ts...>>;
}; };
template <bool bTrue, typename... Ts> template <bool bTrue, typename... Ts>
@ -77,12 +77,12 @@ struct TTupleBasicElement
{ {
private: private:
using FValueType = T; using ValueType = T;
FValueType Value; ValueType Value;
public: public:
template <typename Type> requires (CConstructibleFrom<T, Type&&>) template <typename 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 F##Name##Type = T; \ using Name##Type = T; \
F##Name##Type Name; \ Name##Type Name; \
\ \
template <typename Type> requires (CConstructibleFrom<T, F##Name##Type&&>) \ template <typename 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>>::FType>; using TTupleElement = TCopyCV<U, typename NAMESPACE_PRIVATE::TTupleElementImpl<I, TRemoveCV<U>>::Type>;
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 FSuper = NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>; using Super = NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>;
using FHelper = NAMESPACE_PRIVATE::TTupleHelper<TIndexSequenceFor<Ts...>>; using Helper = 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)
: FSuper(NAMESPACE_PRIVATE::ForwardingConstructor, Forward<Us>(Args)...) : Super(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)
: FSuper(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue) : Super(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)
: FSuper(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue)) : Super(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)
{ {
FHelper::Assign(*this, InValue); Helper::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)
{ {
FHelper::Assign(*this, MoveTemp(InValue)); Helper::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 FResult = TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...>; using R = TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...>;
return NAMESPACE_PRIVATE::TTupleThreeWay<FResult, TMakeIndexSequence<sizeof...(Ts)>>::Do(LHS, RHS); return NAMESPACE_PRIVATE::TTupleThreeWay<R, 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 FHelper::Apply(Forward<F>(Func), static_cast< TTuple& >(*this)); } template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) & { return Helper::Apply(Forward<F>(Func), static_cast< TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const & { return FHelper::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 Helper::Apply(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile& { return FHelper::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 Helper::Apply(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile& { return 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) const volatile& { return Helper::Apply(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) && { return FHelper::Apply(Forward<F>(Func), static_cast< TTuple&&>(*this)); } template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) && { return Helper::Apply(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const && { return FHelper::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 Helper::Apply(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile&& { return FHelper::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 Helper::Apply(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile&& { return 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) const volatile&& { return Helper::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 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) & { return Helper::Transform(Forward<F>(Func), static_cast< TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const & { return 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) const & { return Helper::Transform(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile& { return 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) volatile& { return Helper::Transform(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile& { return 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) const volatile& { return Helper::Transform(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) && { return FHelper::Transform(Forward<F>(Func), static_cast< TTuple&&>(*this)); } template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) && { return Helper::Transform(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const && { return 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) const && { return Helper::Transform(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile&& { return 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) volatile&& { return Helper::Transform(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile&& { return 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) const volatile&& { return Helper::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 FHelper::template Construct<T>(static_cast< TTuple& >(*this)); } template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() & { return Helper::template Construct<T>(static_cast< TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const & { return FHelper::template Construct<T>(static_cast<const TTuple& >(*this)); } template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const & { return Helper::template Construct<T>(static_cast<const TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile& { return FHelper::template Construct<T>(static_cast< volatile TTuple& >(*this)); } template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile& { return Helper::template Construct<T>(static_cast< volatile TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const volatile& { return FHelper::template Construct<T>(static_cast<const volatile TTuple& >(*this)); } template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const volatile& { return Helper::template Construct<T>(static_cast<const volatile TTuple& >(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() && { return FHelper::template Construct<T>(static_cast< TTuple&&>(*this)); } template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() && { return Helper::template Construct<T>(static_cast< TTuple&&>(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const && { return FHelper::template Construct<T>(static_cast<const TTuple&&>(*this)); } template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const && { return Helper::template Construct<T>(static_cast<const TTuple&&>(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile&& { return FHelper::template Construct<T>(static_cast< volatile TTuple&&>(*this)); } template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile&& { return Helper::template Construct<T>(static_cast< volatile TTuple&&>(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const volatile&& { return FHelper::template Construct<T>(static_cast<const 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)); }
/** @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 FType = typename TTupleCatResultImpl<TTupleTypes..., Ts...>::FType; using Type = typename TTupleCatResultImpl<TTupleTypes..., Ts...>::Type;
}; };
template <typename... Ts> template <typename... Ts>
struct TTupleCatResultImpl<FTupleEndFlag, Ts...> struct TTupleCatResultImpl<FTupleEndFlag, Ts...>
{ {
using FType = TTuple<Ts...>; using Type = 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 FForwardType { using FType = TConditional<CRValueReference<T>, TRemoveReference<U>&&, U>; }; struct ForwardType { using Type = 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 FForwardType<RTypes, decltype(Forward<TTupleType>(InValue).template GetValue<Indices>())>::FType> static_cast<typename ForwardType<RTypes, decltype(Forward<TTupleType>(InValue).template GetValue<Indices>())>::Type>
( (
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>::FType; using TTupleCatResult = typename NAMESPACE_PRIVATE::TTupleCatResultImpl<TRemoveReference<TTupleTypes>..., NAMESPACE_PRIVATE::FTupleEndFlag>::Type;;
/** 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 FResult = TTupleCatResult<TTupleTypes...>; using R = TTupleCatResult<TTupleTypes...>;
if constexpr (sizeof...(Args) == 0) return FResult(); if constexpr (sizeof...(Args) == 0) return R();
else return NAMESPACE_PRIVATE::TTupleCatImpl<FResult>::Do(Forward<TTupleTypes>(Args)...); else return NAMESPACE_PRIVATE::TTupleCatImpl<R>::Do(Forward<TTupleTypes>(Args)...);
} }
/** /**
@ -679,22 +679,20 @@ 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 FType = TTuple<TCommonType<Ts, Us>...>; using Type = 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 FType = TTuple<TCommonReference<TQualifiers<Ts>, UQualifiers<Us>>...>; using Type = 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.
@ -720,5 +718,3 @@ 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 FCastType = TRemoveReference<T>; using CastType = TRemoveReference<T>;
return static_cast<FCastType&&>(Obj); return static_cast<CastType&&>(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 FType = Meta::TType<I, TTypeSequence<Ts...>>; using Type = Meta::TType<I, TTypeSequence<Ts...>>;
}; };
template <typename T, typename TSequence> template <typename T, typename TSequence>
struct TVariantOverloadType struct TVariantOverloadType
{ {
using FFrontType = Meta::TFront<TSequence>; using FrontType = Meta::TFront<TSequence>;
using FNextSequence = Meta::TPop<TSequence>; using NextSequence = Meta::TPop<TSequence>;
using FNextUniqueSequence = typename TVariantOverloadType<T, FNextSequence>::FType; using NextUniqueSequence = typename TVariantOverloadType<T, NextSequence>::Type;
// T_i x[] = { Forward<T>(t) }; // T_i x[] = { Forward<T>(t) };
static constexpr bool bConditional = requires { DeclVal<void(FFrontType(&&)[1])>()({ DeclVal<T>() }); }; static constexpr bool bConditional = requires { DeclVal<void(FrontType(&&)[1])>()({ DeclVal<T>() }); };
using FType = TConditional<bConditional, Meta::TPush<FFrontType, FNextUniqueSequence>, FNextUniqueSequence>; using Type = TConditional<bConditional, Meta::TPush<FrontType, NextUniqueSequence>, NextUniqueSequence>;
}; };
template <typename T> template <typename T>
struct TVariantOverloadType<T, TTypeSequence<>> struct TVariantOverloadType<T, TTypeSequence<>>
{ {
using FType = TTypeSequence<>; using Type = TTypeSequence<>;
}; };
template <typename T, typename... Ts> template <typename T, typename... Ts>
using TVariantSelectedType = Meta::TOverloadResolution<T, typename NAMESPACE_PRIVATE::TVariantOverloadType<T, TTypeSequence<Ts...>>::FType>; using TVariantSelectedType = Meta::TOverloadResolution<T, typename NAMESPACE_PRIVATE::TVariantOverloadType<T, TTypeSequence<Ts...>>::Type>;
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>>::FType>; using TVariantAlternative = TCopyCV<U, typename NAMESPACE_PRIVATE::TVariantAlternativeImpl<I, TRemoveCV<U>>::Type>;
/** /**
* 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 FSelectedType = TVariantAlternative<I, TVariant<Ts...>>; using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
new (&Value) FSelectedType(Forward<Us>(Args)...); new (&Value) SelectedType(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 FSelectedType = TVariantAlternative<I, TVariant<Ts...>>; using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
new (&Value) FSelectedType(IL, Forward<Us>(Args)...); new (&Value) SelectedType(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 FSelectedType = NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>; using SelectedType = NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>;
if (GetIndex() == TVariantIndex<FSelectedType, TVariant<Ts...>>) GetValue<FSelectedType>() = Forward<T>(InValue); if (GetIndex() == TVariantIndex<SelectedType, TVariant<Ts...>>) GetValue<SelectedType>() = Forward<T>(InValue);
else else
{ {
Reset(); Reset();
new (&Value) FSelectedType(Forward<T>(InValue)); new (&Value) SelectedType(Forward<T>(InValue));
TypeIndex = TVariantIndex<FSelectedType, TVariant<Ts...>>; TypeIndex = TVariantIndex<SelectedType, 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 FSelectedType = TVariantAlternative<I, TVariant<Ts...>>; using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
FSelectedType* Result = new (&Value) FSelectedType(Forward<Us>(Args)...); SelectedType* Result = new (&Value) SelectedType(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 FSelectedType = TVariantAlternative<I, TVariant<Ts...>>; using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
FSelectedType* Result = new (&Value) FSelectedType(IL, Forward<Us>(Args)...); SelectedType* Result = new (&Value) SelectedType(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 FGetTotalNum struct GetTotalNum
{ {
FORCEINLINE static constexpr size_t Do() FORCEINLINE static constexpr size_t Do()
{ {
@ -464,10 +464,10 @@ struct TVariantVisitImpl
} }
return Result; return Result;
} };
}; };
struct FEncodeIndices struct EncodeIndices
{ {
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 FDecodeExtent struct DecodeExtent
{ {
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 FInvokeEncoded; struct InvokeEncoded;
template <size_t EncodedIndex, size_t... ExtentIndices> template <size_t EncodedIndex, size_t... ExtentIndices>
struct FInvokeEncoded<EncodedIndex, TIndexSequence<ExtentIndices...>> struct InvokeEncoded<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<FDecodeExtent::Do(EncodedIndex, ExtentIndices)>()...); return Invoke(Forward<F>(Func), Forward<VariantTypes>(Variants).template GetValue<DecodeExtent::Do(EncodedIndex, ExtentIndices)>()...);
} }
template <typename Ret> template <typename Ret>
struct FResult struct Result
{ {
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<FDecodeExtent::Do(EncodedIndex, ExtentIndices)>()...); return InvokeResult<Ret>(Forward<F>(Func), Forward<VariantTypes>(Variants).template GetValue<DecodeExtent::Do(EncodedIndex, ExtentIndices)>()...);
} }
}; };
}; };
template <typename> template <typename>
struct FInvokeVariant; struct InvokeVariant;
template <size_t... EncodedIndices> template <size_t... EncodedIndices>
struct FInvokeVariant<TIndexSequence<EncodedIndices...>> struct InvokeVariant<TIndexSequence<EncodedIndices...>>
{ {
FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants) FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants)
{ {
using FExtentIndices = TIndexSequenceFor<VariantTypes...>; using ExtentIndices = TIndexSequenceFor<VariantTypes...>;
using FResultType = TCommonType<decltype(FInvokeEncoded<EncodedIndices, FExtentIndices>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...))...>; using ResultType = TCommonType<decltype(InvokeEncoded<EncodedIndices, ExtentIndices>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...))...>;
using InvokeImplType = ResultType(*)(F&&, VariantTypes&&...);
using FInvokeImplType = FResultType(*)(F&&, VariantTypes&&...); constexpr InvokeImplType InvokeImpl[] = { InvokeEncoded<EncodedIndices, ExtentIndices>::template Result<ResultType>::Do... };
constexpr FInvokeImplType InvokeImpl[] = { FInvokeEncoded<EncodedIndices, FExtentIndices>::template FResult<FResultType>::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)...);
} }
template <typename Ret> template <typename Ret>
struct FResult struct Result
{ {
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants) FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants)
{ {
using FExtentIndices = TIndexSequenceFor<VariantTypes...>; using ExtentIndices = TIndexSequenceFor<VariantTypes...>;
using FInvokeImplType = Ret(*)(F&&, VariantTypes&&...); using InvokeImplType = Ret(*)(F&&, VariantTypes&&...);
constexpr FInvokeImplType InvokeImpl[] = { FInvokeEncoded<EncodedIndices, FExtentIndices>::template FResult<Ret>::Do... }; constexpr InvokeImplType InvokeImpl[] = { InvokeEncoded<EncodedIndices, ExtentIndices>::template Result<Ret>::Do... };
return InvokeImpl[FEncodeIndices::Do({ Variants.GetIndex()... })](Forward<F>(Func), Forward<VariantTypes>(Variants)...); return InvokeImpl[EncodeIndices::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 FInvokeVariant<TMakeIndexSequence<FGetTotalNum::Do()>>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...); return InvokeVariant<TMakeIndexSequence<GetTotalNum::Do()>>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...);
} }
template <typename Ret> template <typename Ret>
struct FResult struct Result
{ {
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants) FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants)
{ {
return FInvokeVariant<TMakeIndexSequence<FGetTotalNum::Do()>>::template FResult<Ret>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...); return InvokeVariant<TMakeIndexSequence<GetTotalNum::Do()>>::template Result<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 FResult<Ret>::Do(Forward<F>(Func), Forward<FirstVariantType>(FirstVariant), Forward<VariantTypes>(Variants)...); return NAMESPACE_PRIVATE::TVariantVisitImpl<F, FirstVariantType, VariantTypes...>::template Result<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 FType // If sizeof...(Ts) is zero, there is no member Type
template <> template <>
struct TCommonTypeImpl<> { }; struct TCommonTypeImpl<> { };
// 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 // 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
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 FType names the same type as TCommonType<TDecay<T>, TDecay<U>>, if it exists; if not, there is no member FType // 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
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>::FType, that specialization is used // Otherwise, if there is a user specialization for TBasicCommonType<T, U>::Type, that specialization is used
template <typename T, typename U> concept CBasicCommonType = requires { typename TBasicCommonType<T, U>::FType; }; template <typename T, typename U> concept CBasicCommonType = requires { typename TBasicCommonType<T, U>::Type; };
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>::FType and TBasicCommonType<U, T>::FType must denote the same type // Additionally, TBasicCommonType<T, U>::Type and TBasicCommonType<U, T>::Type must denote the same type
static_assert(CSameAs<typename TBasicCommonType<T, U>::FType, TDecay<typename TBasicCommonType<T, U>::FType>>, "The basic common type must be a cv-unqualified non-reference type"); static_assert(CSameAs<typename TBasicCommonType<T, U>::Type, TDecay<typename TBasicCommonType<T, U>::Type>>, "The basic common type must be a cv-unqualified non-reference type");
static_assert(CConstructibleFrom<typename TBasicCommonType<T, U>::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(CConstructibleFrom<typename TBasicCommonType<T, U>::Type, T&&> && CConstructibleFrom<typename TBasicCommonType<T, U>::Type, U&&>, "The basic common type must be a type which both T and U are explicitly convertible");
static_assert(CSameAs<typename TBasicCommonType<T, U>::FType, typename TBasicCommonType<U, T>::FType>, "TBasicCommonType<T, U>::FType and TBasicCommonType<U, T>::FType must denote the same type"); 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");
}; };
// Otherwise, if TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())> is a valid type, the member FType denotes that type // Otherwise, if TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())> is a valid Type, the member Type 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 FType = TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())>; }; struct TCommonTypeImpl<T, U> { using Type = 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 FType denotes that type // where CRT and CRU are const TRemoveReference<T>& and const TRemoveReference<U>& respectively, the member Type 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 FType = TDecay<decltype(false ? DeclVal<const TRemoveReference<T>&>() : DeclVal<const TRemoveReference<U>&>())>; }; struct TCommonTypeImpl<T, U> { using Type = TDecay<decltype(false ? DeclVal<const TRemoveReference<T>&>() : DeclVal<const TRemoveReference<U>&>())>; };
// Otherwise, there is no member FType // Otherwise, there is no member Type
// If sizeof...(Ts) is greater than two // If sizeof...(Ts) is greater than two
// If TCommonType<T, U> exists, the member FType denotes TCommonType<TCommonType<T, U>, R...> if such a type exists // If TCommonType<T, U> exists, the member Type denotes TCommonType<TCommonType<T, U>, R...> if such a Type exists
template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonTypeImpl<T, U>::FType; }) template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonTypeImpl<T, U>::Type; })
struct TCommonTypeImpl<T, U, W, Ts...> : TCommonTypeImpl<typename TCommonTypeImpl<T, U>::FType, W, Ts...> { }; struct TCommonTypeImpl<T, U, W, Ts...> : TCommonTypeImpl<typename TCommonTypeImpl<T, U>::Type, W, Ts...> { };
// In all other cases, there is no member FType // In all other cases, there is no member Type
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 FType // If sizeof...(T) is zero, there is no member Type
template <> template <>
struct TCommonReferenceImpl<> { }; struct TCommonReferenceImpl<> { };
// If sizeof...(T) is one, the member FType names the same type as T // If sizeof...(T) is one, the member Type names the same Type as T
template <typename T> template <typename T>
struct TCommonReferenceImpl<T> { using FType = T; }; struct TCommonReferenceImpl<T> { using Type = 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 FType 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 Type Type names S
template <typename T, typename U> concept CSimpleCommonReference = requires { typename TSimpleCommonReferenceImpl<T, U>::FType; }; template <typename T, typename U> concept CSimpleCommonReference = requires { typename TSimpleCommonReferenceImpl<T, U>::Type; };
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>::FType exists // Otherwise, if TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQ, UQ>::Type exists
template <typename T, typename U> struct TBasicCommonReferenceImpl : TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQualifiersImpl<T>::template FApply, TQualifiersImpl<U>::template FApply> { }; template <typename T, typename U> struct TBasicCommonReferenceImpl : TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQualifiersImpl<T>::template Apply, TQualifiersImpl<U>::template Apply> { };
template <typename T, typename U> concept CBasicCommonReference = requires { typename TBasicCommonReferenceImpl<T, U>::FType; }; template <typename T, typename U> concept CBasicCommonReference = requires { typename TBasicCommonReferenceImpl<T, U>::Type; };
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>::FType and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::FType must denote the same type // Additionally, TBasicCommonReference<T, U, TQualifiers, UQualifiers>::Type and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::Type must denote the same type
static_assert(CConvertibleTo<T, typename TBasicCommonReferenceImpl<T, U>::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(CConvertibleTo<T, typename TBasicCommonReferenceImpl<T, U>::Type> && CConvertibleTo<U, typename TBasicCommonReferenceImpl<T, U>::Type>, "The basic common reference must be a type to which both TQualifiers<T> and UQualifiers<U> are convertible");
static_assert(CSameAs<typename TBasicCommonReferenceImpl<T, U>::FType, typename TBasicCommonReferenceImpl<U, T>::FType>, "TBasicCommonReference<T, U, TQualifiers, UQualifiers>::FType and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::FType must denote the same type"); 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");
}; };
// 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 // Where TQ and UQ is a unary alias template such that TQ<U> is U with the addition of T's cv-ref qualifiers, then the member Type Type names that Type
template <typename T> struct TQualifiersImpl { template <typename U> using FApply = TCopyCV<T, U>; }; template <typename T> struct TQualifiersImpl { template <typename U> using Apply = 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 = TAddLValueReference<TCopyCV<T, U>>; };
template <typename T> struct TQualifiersImpl<T&&> { template <typename U> using FApply = TAddRValueReference<TCopyCV<T, U>>; }; template <typename T> struct TQualifiersImpl<T&&> { template <typename U> using Apply = TAddRValueReference<TCopyCV<T, U>>; };
// 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 // 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
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 FType = decltype(false ? Val<T>() : Val<U>()); }; struct TCommonReferenceImpl<T, U> { using Type = decltype(false ? Val<T>() : Val<U>()); };
// Otherwise, if TCommonType<T, U> is a valid type, then the member FType names that type // Otherwise, if TCommonType<T, U> is a valid Type, then the member Type Type 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 FType // Otherwise, there is no member Type
// If sizeof...(Ts) is greater than two // If sizeof...(Ts) is greater than two
// If TCommonReference<T, U> exists, the member FType denotes TCommonReference<TCommonReference<T, U>, R...> if such a type exists // If TCommonReference<T, U> exists, the member Type denotes TCommonReference<TCommonReference<T, U>, R...> if such a Type exists
template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonReferenceImpl<T, U>::FType; }) template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonReferenceImpl<T, U>::Type; })
struct TCommonReferenceImpl<T, U, W, Ts...> : TCommonReferenceImpl<typename TCommonReferenceImpl<T, U>::FType, W, Ts...> { }; struct TCommonReferenceImpl<T, U, W, Ts...> : TCommonReferenceImpl<typename TCommonReferenceImpl<T, U>::Type, W, Ts...> { };
// In all other cases, there is no member FType // In all other cases, there is no member Type
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 FType = 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>&>()); };
// 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&>::FType> &&> && CConvertibleTo<U&&, TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::FType> &&>) template <typename T, typename U> requires (CConvertibleTo<T&&, TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::Type> &&> && CConvertibleTo<U&&, TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::Type> &&>)
struct TSimpleCommonReferenceImpl<T&&, U&&> { using FType = TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::FType> &&; }; struct TSimpleCommonReferenceImpl<T&&, U&&> { using Type = TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::Type> &&; };
// Otherwise, one of the two types must be a lvalue reference type A & and the other must be a rvalue reference type B && // Otherwise, one of the two types must be an lvalue reference Type A & and the other must be an rvalue reference Type B &&
// Let D denote the simple common reference type of A & and B const &, if any // 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&>::FType>) template <typename T, typename U> requires (CConvertibleTo<U&&, typename TSimpleCommonReferenceImpl<T&, const U&>::Type>)
struct TSimpleCommonReferenceImpl<T&, U&&> { using FType = typename TSimpleCommonReferenceImpl<T&, const U&>::FType; }; struct TSimpleCommonReferenceImpl<T&, U&&> { using Type = typename TSimpleCommonReferenceImpl<T&, const U&>::Type; };
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...>::FType; template <typename... Ts> using TCommonType = typename NAMESPACE_PRIVATE::TCommonTypeImpl<Ts...>::Type;
template <typename... Ts> using TCommonReference = typename NAMESPACE_PRIVATE::TCommonReferenceImpl<Ts...>::FType; template <typename... Ts> using TCommonReference = typename NAMESPACE_PRIVATE::TCommonReferenceImpl<Ts...>::Type;
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 FType = To; }; template <typename From, typename To> struct TCopyConstImpl { using Type = To; };
template <typename From, typename To> struct TCopyConstImpl<const From, To> { using FType = const To; }; template <typename From, typename To> struct TCopyConstImpl<const From, To> { using Type = const To; };
template <typename From, typename To> struct TCopyVolatileImpl { using FType = To; }; template <typename From, typename To> struct TCopyVolatileImpl { using Type = To; };
template <typename From, typename To> struct TCopyVolatileImpl<volatile From, To> { using FType = volatile To; }; template <typename From, typename To> struct TCopyVolatileImpl<volatile From, To> { using Type = volatile To; };
template <typename From, typename To> struct TCopyCVImpl { using FType = typename TCopyConstImpl<From, typename TCopyVolatileImpl<From, To>::FType>::FType; }; template <typename From, typename To> struct TCopyCVImpl { using Type = typename TCopyConstImpl<From, typename TCopyVolatileImpl<From, To>::Type>::Type; };
template <typename From, typename To> struct TCopyReferenceImpl { using FType = To; }; template <typename From, typename To> struct TCopyReferenceImpl { 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 TCopyReferenceImpl<From&&, To> { using Type = To&&; };
template <typename From, typename To> struct TCopyCVRefImpl { using FType = typename TCopyCVImpl<From, To>::FType; }; template <typename From, typename To> struct TCopyCVRefImpl { 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&&; }; template <typename From, typename To> struct TCopyCVRefImpl<From&&, To&&> { using Type = typename TCopyCVImpl<From, To>::Type&&; };
NAMESPACE_PRIVATE_END NAMESPACE_PRIVATE_END
template <typename From, typename To> using TCopyConst = typename NAMESPACE_PRIVATE::TCopyConstImpl <From, To>::FType; template <typename From, typename To> using TCopyConst = typename NAMESPACE_PRIVATE::TCopyConstImpl<From, To>::Type;
template <typename From, typename To> using TCopyVolatile = typename NAMESPACE_PRIVATE::TCopyVolatileImpl <From, To>::FType; template <typename From, typename To> using TCopyVolatile = typename NAMESPACE_PRIVATE::TCopyVolatileImpl<From, To>::Type;
template <typename From, typename To> using TCopyCV = typename NAMESPACE_PRIVATE::TCopyCVImpl <From, To>::FType; template <typename From, typename To> using TCopyCV = typename NAMESPACE_PRIVATE::TCopyCVImpl<From, To>::Type;
template <typename From, typename To> using TCopyReference = typename NAMESPACE_PRIVATE::TCopyReferenceImpl<From, To>::FType; template <typename From, typename To> using TCopyReference = typename NAMESPACE_PRIVATE::TCopyReferenceImpl<From, To>::Type;
template <typename From, typename To> using TCopyCVRef = typename NAMESPACE_PRIVATE::TCopyCVRefImpl <From, To>::FType; template <typename From, typename To> using TCopyCVRef = typename NAMESPACE_PRIVATE::TCopyCVRefImpl<From, To>::Type;
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 T, T InValue> template <typename InType, InType InValue>
struct TConstant struct TConstant
{ {
using FValueType = T; using ValueType = InType;
using FType = TConstant; using Type = TConstant;
static constexpr FValueType Value = InValue; static constexpr ValueType Value = InValue;
FORCEINLINE constexpr operator FValueType() const { return Value; } FORCEINLINE constexpr operator ValueType() const { return Value; }
FORCEINLINE constexpr FValueType operator()() const { return Value; } FORCEINLINE constexpr ValueType operator()() const { return Value; }
}; };
template <bool InValue> template <bool InValue>