Compare commits
2 Commits
d88eb4be5e
...
312cfe4097
Author | SHA1 | Date | |
---|---|---|---|
312cfe4097 | |||
d2b6e0c669 |
@ -46,7 +46,7 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FMemoryLeakChecker MemoryLeakChecker;
|
FMemoryLeakChecker GMemoryLeakChecker;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ void* Malloc(size_t Count, size_t Alignment)
|
|||||||
|
|
||||||
check(Result != nullptr);
|
check(Result != nullptr);
|
||||||
|
|
||||||
check_code({ MemoryLeakChecker.AddMemoryAllocationCount(); });
|
check_code({ GMemoryLeakChecker.AddMemoryAllocationCount(); });
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -139,7 +139,7 @@ void Free(void* Ptr)
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
check_code({ MemoryLeakChecker.ReleaseMemoryAllocationCount(); });
|
check_code({ GMemoryLeakChecker.ReleaseMemoryAllocationCount(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t QuantizeSize(size_t Count, size_t Alignment)
|
size_t QuantizeSize(size_t Count, size_t Alignment)
|
||||||
|
@ -10,15 +10,15 @@ NAMESPACE_BEGIN(Math)
|
|||||||
|
|
||||||
NAMESPACE_UNNAMED_BEGIN
|
NAMESPACE_UNNAMED_BEGIN
|
||||||
|
|
||||||
TAtomic<uint32> RandState = 586103306;
|
TAtomic<uint32> GRandState = 586103306;
|
||||||
|
|
||||||
NAMESPACE_UNNAMED_END
|
NAMESPACE_UNNAMED_END
|
||||||
|
|
||||||
uint32 Seed(uint32 InSeed)
|
uint32 Seed(uint32 InSeed)
|
||||||
{
|
{
|
||||||
uint32 OldSeed = RandState.Load(EMemoryOrder::Relaxed);
|
uint32 OldSeed = GRandState.Load(EMemoryOrder::Relaxed);
|
||||||
|
|
||||||
if (InSeed != 0) RandState.Store(InSeed, EMemoryOrder::Relaxed);
|
if (InSeed != 0) GRandState.Store(InSeed, EMemoryOrder::Relaxed);
|
||||||
|
|
||||||
return OldSeed;
|
return OldSeed;
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@ uint32 Rand()
|
|||||||
{
|
{
|
||||||
uint32 Result;
|
uint32 Result;
|
||||||
|
|
||||||
RandState.FetchFn(
|
GRandState.FetchFn(
|
||||||
[&Result](uint32 Value)
|
[&Result](uint32 Value)
|
||||||
{
|
{
|
||||||
Result = Value;
|
Result = Value;
|
||||||
|
@ -7,6 +7,8 @@ NAMESPACE_REDCRAFT_BEGIN
|
|||||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||||
NAMESPACE_MODULE_BEGIN(Utility)
|
NAMESPACE_MODULE_BEGIN(Utility)
|
||||||
|
|
||||||
|
// ReSharper disable CppInconsistentNaming
|
||||||
|
|
||||||
NAMESPACE_BEGIN(Testing)
|
NAMESPACE_BEGIN(Testing)
|
||||||
|
|
||||||
void TestContainers()
|
void TestContainers()
|
||||||
@ -603,6 +605,8 @@ void TestList()
|
|||||||
|
|
||||||
NAMESPACE_END(Testing)
|
NAMESPACE_END(Testing)
|
||||||
|
|
||||||
|
// ReSharper restore CppInconsistentNaming
|
||||||
|
|
||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
NAMESPACE_MODULE_END(Redcraft)
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
NAMESPACE_REDCRAFT_END
|
NAMESPACE_REDCRAFT_END
|
||||||
|
@ -255,23 +255,23 @@ void TestPointerTraits()
|
|||||||
always_check(!TPointerTraits<int64>::bIsPointer);
|
always_check(!TPointerTraits<int64>::bIsPointer);
|
||||||
|
|
||||||
always_check(TPointerTraits<int64*>::bIsPointer);
|
always_check(TPointerTraits<int64*>::bIsPointer);
|
||||||
always_check((CSameAs<TPointerTraits<int64*>::PointerType, int64*>));
|
always_check((CSameAs<TPointerTraits<int64*>::FPointerType, int64*>));
|
||||||
always_check((CSameAs<TPointerTraits<int64*>::ElementType, int64>));
|
always_check((CSameAs<TPointerTraits<int64*>::FElementType, int64>));
|
||||||
always_check(TPointerTraits<int64*>::ToAddress(nullptr) == nullptr);
|
always_check(TPointerTraits<int64*>::ToAddress(nullptr) == nullptr);
|
||||||
|
|
||||||
always_check(TPointerTraits<int64(*)[]>::bIsPointer);
|
always_check(TPointerTraits<int64(*)[]>::bIsPointer);
|
||||||
always_check((CSameAs<TPointerTraits<int64(*)[]>::PointerType, int64(*)[]>));
|
always_check((CSameAs<TPointerTraits<int64(*)[]>::FPointerType, int64(*)[]>));
|
||||||
always_check((CSameAs<TPointerTraits<int64(*)[]>::ElementType, int64>));
|
always_check((CSameAs<TPointerTraits<int64(*)[]>::FElementType, int64>));
|
||||||
always_check(TPointerTraits<int64*>::ToAddress(nullptr) == nullptr);
|
always_check(TPointerTraits<int64*>::ToAddress(nullptr) == nullptr);
|
||||||
|
|
||||||
always_check(TPointerTraits<TSharedPtr<int64>>::bIsPointer);
|
always_check(TPointerTraits<TSharedPtr<int64>>::bIsPointer);
|
||||||
always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::PointerType, TSharedPtr<int64>>));
|
always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::FPointerType, TSharedPtr<int64>>));
|
||||||
always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::ElementType, int64>));
|
always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::FElementType, int64>));
|
||||||
always_check(TPointerTraits<TSharedPtr<int64>>::ToAddress(nullptr) == nullptr);
|
always_check(TPointerTraits<TSharedPtr<int64>>::ToAddress(nullptr) == nullptr);
|
||||||
|
|
||||||
always_check(TPointerTraits<TSharedPtr<int64[]>>::bIsPointer);
|
always_check(TPointerTraits<TSharedPtr<int64[]>>::bIsPointer);
|
||||||
always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::PointerType, TSharedPtr<int64[]>>));
|
always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::FPointerType, TSharedPtr<int64[]>>));
|
||||||
always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::ElementType, int64>));
|
always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::FElementType, int64>));
|
||||||
always_check(TPointerTraits<TSharedPtr<int64[]>>::ToAddress(nullptr) == nullptr);
|
always_check(TPointerTraits<TSharedPtr<int64[]>>::ToAddress(nullptr) == nullptr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -64,9 +64,9 @@ void TestInvoke()
|
|||||||
|
|
||||||
void TestReferenceWrapper()
|
void TestReferenceWrapper()
|
||||||
{
|
{
|
||||||
typedef int32(*FuncType)(int32, int32, int32);
|
typedef int32(*FFuncType)(int32, int32, int32);
|
||||||
FuncType TempA = [](int32 A, int32 B, int32 C) -> int32 { return A * B * C; };
|
FFuncType TempA = [](int32 A, int32 B, int32 C) -> int32 { return A * B * C; };
|
||||||
TReferenceWrapper<FuncType> TempB(TempA);
|
TReferenceWrapper<FFuncType> TempB(TempA);
|
||||||
always_check(TempB(1, 1, 1) == 1);
|
always_check(TempB(1, 1, 1) == 1);
|
||||||
TempB.Get() = &TestFunctionA;
|
TempB.Get() = &TestFunctionA;
|
||||||
always_check(TempA(1, 1, 1) == 3);
|
always_check(TempA(1, 1, 1) == 3);
|
||||||
@ -330,14 +330,15 @@ void TestVariant()
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
using VariantType = TVariant<int32, int64, float64>;
|
using FVariantType = TVariant<int32, int64, float64>;
|
||||||
VariantType TempArray[] = { 10, 15ll, 1.5 };
|
FVariantType TempArray[] = { 10, 15ll, 1.5 };
|
||||||
|
|
||||||
for(auto&& TempA : TempArray)
|
for(auto&& TempA : TempArray)
|
||||||
{
|
{
|
||||||
Visit(
|
Visit(
|
||||||
[](auto&& A)
|
[](auto&& A)
|
||||||
{
|
{
|
||||||
|
// ReSharper disable once CppInconsistentNaming
|
||||||
using T = TRemoveCVRef<decltype(A)>;
|
using T = TRemoveCVRef<decltype(A)>;
|
||||||
if constexpr (CSameAs<T, int32>) always_check(A == 10);
|
if constexpr (CSameAs<T, int32>) always_check(A == 10);
|
||||||
else if constexpr (CSameAs<T, int64>) always_check(A == 15ll);
|
else if constexpr (CSameAs<T, int64>) always_check(A == 15ll);
|
||||||
@ -347,11 +348,12 @@ void TestVariant()
|
|||||||
TempA
|
TempA
|
||||||
);
|
);
|
||||||
|
|
||||||
VariantType TempB = Visit([](auto&& A) -> VariantType { return A + A; }, TempA);
|
FVariantType TempB = Visit([](auto&& A) -> FVariantType { return A + A; }, TempA);
|
||||||
|
|
||||||
Visit(
|
Visit(
|
||||||
[](auto&& A, auto&& B)
|
[](auto&& A, auto&& B)
|
||||||
{
|
{
|
||||||
|
// ReSharper disable once CppInconsistentNaming
|
||||||
using T = TRemoveCVRef<decltype(A)>;
|
using T = TRemoveCVRef<decltype(A)>;
|
||||||
if constexpr (CSameAs<T, int32>) always_check(A == 10 && B == 20);
|
if constexpr (CSameAs<T, int32>) always_check(A == 10 && B == 20);
|
||||||
else if constexpr (CSameAs<T, int64>) always_check(A == 15ll && B == 30ll);
|
else if constexpr (CSameAs<T, int64>) always_check(A == 15ll && B == 30ll);
|
||||||
@ -366,6 +368,7 @@ void TestVariant()
|
|||||||
Visit(
|
Visit(
|
||||||
[](auto&& A)
|
[](auto&& A)
|
||||||
{
|
{
|
||||||
|
// ReSharper disable once CppInconsistentNaming
|
||||||
using T = TRemoveCVRef<decltype(A)>;
|
using T = TRemoveCVRef<decltype(A)>;
|
||||||
if constexpr (CSameAs<T, int32>) always_check(A == 20);
|
if constexpr (CSameAs<T, int32>) always_check(A == 20);
|
||||||
else if constexpr (CSameAs<T, int64>) always_check(A == 30ll);
|
else if constexpr (CSameAs<T, int64>) always_check(A == 30ll);
|
||||||
@ -417,6 +420,7 @@ void TestVariant()
|
|||||||
|
|
||||||
auto TestQualifiers = [&bIsConst, &bIsLValue, &bIsRValue](auto&& A) -> int32
|
auto TestQualifiers = [&bIsConst, &bIsLValue, &bIsRValue](auto&& A) -> int32
|
||||||
{
|
{
|
||||||
|
// ReSharper disable once CppInconsistentNaming
|
||||||
using T = decltype(A);
|
using T = decltype(A);
|
||||||
always_check(A == 10);
|
always_check(A == 10);
|
||||||
always_check(CConst<TRemoveReference<T>> == bIsConst);
|
always_check(CConst<TRemoveReference<T>> == bIsConst);
|
||||||
@ -429,6 +433,8 @@ void TestVariant()
|
|||||||
bIsLValue = true;
|
bIsLValue = true;
|
||||||
bIsRValue = false;
|
bIsRValue = false;
|
||||||
|
|
||||||
|
// ReSharper disable CppInconsistentNaming
|
||||||
|
|
||||||
TVariant<int32> TempLA = 10;
|
TVariant<int32> TempLA = 10;
|
||||||
auto ReturnLA = Visit(TestQualifiers, TempLA);
|
auto ReturnLA = Visit(TestQualifiers, TempLA);
|
||||||
always_check((CSameAs<int32, decltype(ReturnLA)>));
|
always_check((CSameAs<int32, decltype(ReturnLA)>));
|
||||||
@ -488,6 +494,8 @@ void TestVariant()
|
|||||||
const TVariant<int32> TempRD = TempLC;
|
const TVariant<int32> TempRD = TempLC;
|
||||||
auto ReturnRD = Visit<int32>(TestQualifiers, MoveTemp(TempRD));
|
auto ReturnRD = Visit<int32>(TestQualifiers, MoveTemp(TempRD));
|
||||||
always_check((CSameAs<int32, decltype(ReturnRD)>));
|
always_check((CSameAs<int32, decltype(ReturnRD)>));
|
||||||
|
|
||||||
|
// ReSharper restore CppInconsistentNaming
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -869,11 +877,11 @@ void TestTuple()
|
|||||||
// always_check((CSameAs<TTupleElement<4, TTuple<double, float&, char&&>>, double>));
|
// always_check((CSameAs<TTupleElement<4, TTuple<double, float&, char&&>>, double>));
|
||||||
|
|
||||||
{
|
{
|
||||||
using Type = TTuple<int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64,
|
using FType = TTuple<int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64,
|
||||||
int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64,
|
int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64,
|
||||||
int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64>;
|
int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64>;
|
||||||
|
|
||||||
Type Temp;
|
FType Temp;
|
||||||
|
|
||||||
Temp.First = 0;
|
Temp.First = 0;
|
||||||
Temp.Second = 0;
|
Temp.Second = 0;
|
||||||
@ -892,20 +900,20 @@ void TestTuple()
|
|||||||
Temp.Fifteenth = 0;
|
Temp.Fifteenth = 0;
|
||||||
Temp.Sixteenth = 0;
|
Temp.Sixteenth = 0;
|
||||||
|
|
||||||
always_check(CDefaultConstructible<Type>);
|
always_check(CDefaultConstructible<FType>);
|
||||||
always_check(CTriviallyDefaultConstructible<Type>);
|
always_check(CTriviallyDefaultConstructible<FType>);
|
||||||
always_check(CConstructibleFrom<Type>);
|
always_check(CConstructibleFrom<FType>);
|
||||||
always_check(CTriviallyConstructibleFrom<Type>);
|
always_check(CTriviallyConstructibleFrom<FType>);
|
||||||
always_check(CCopyConstructible<Type>);
|
always_check(CCopyConstructible<FType>);
|
||||||
always_check(CTriviallyCopyConstructible<Type>);
|
always_check(CTriviallyCopyConstructible<FType>);
|
||||||
always_check(CMoveConstructible<Type>);
|
always_check(CMoveConstructible<FType>);
|
||||||
always_check(CTriviallyMoveConstructible<Type>);
|
always_check(CTriviallyMoveConstructible<FType>);
|
||||||
always_check(CCopyAssignable<Type>);
|
always_check(CCopyAssignable<FType>);
|
||||||
always_check(CTriviallyCopyAssignable<Type>);
|
always_check(CTriviallyCopyAssignable<FType>);
|
||||||
always_check(CMoveAssignable<Type>);
|
always_check(CMoveAssignable<FType>);
|
||||||
always_check(CTriviallyMoveAssignable<Type>);
|
always_check(CTriviallyMoveAssignable<FType>);
|
||||||
always_check(CDestructible<Type>);
|
always_check(CDestructible<FType>);
|
||||||
always_check(CTriviallyDestructible<Type>);
|
always_check(CTriviallyDestructible<FType>);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -1084,25 +1092,25 @@ struct FFunctionDebug
|
|||||||
void Print(int32 In) { Output[Index++] = In; }
|
void Print(int32 In) { Output[Index++] = In; }
|
||||||
};
|
};
|
||||||
|
|
||||||
FFunctionDebug FunctionDebug;
|
FFunctionDebug GFunctionDebug;
|
||||||
|
|
||||||
struct FPrintAdd
|
struct FPrintAdd
|
||||||
{
|
{
|
||||||
FPrintAdd(int32 InNum) : Num(InNum) { }
|
FPrintAdd(int32 InNum) : Num(InNum) { }
|
||||||
void F(int32 I) const { FunctionDebug.Print(Num + I); }
|
void F(int32 I) const { GFunctionDebug.Print(Num + I); }
|
||||||
int32 Num;
|
int32 Num;
|
||||||
};
|
};
|
||||||
|
|
||||||
void PrintNum(int32 I)
|
void PrintNum(int32 I)
|
||||||
{
|
{
|
||||||
FunctionDebug.Print(I);
|
GFunctionDebug.Print(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FPrintNum
|
struct FPrintNum
|
||||||
{
|
{
|
||||||
void operator()(int32 I) const
|
void operator()(int32 I) const
|
||||||
{
|
{
|
||||||
FunctionDebug.Print(I);
|
GFunctionDebug.Print(I);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1310,7 +1318,7 @@ void TestFunction()
|
|||||||
AddDisplay(314159, 1);
|
AddDisplay(314159, 1);
|
||||||
|
|
||||||
TFunction<int32(FPrintAdd const&)> Num = &FPrintAdd::Num;
|
TFunction<int32(FPrintAdd const&)> Num = &FPrintAdd::Num;
|
||||||
FunctionDebug.Print(Num(Foo));
|
GFunctionDebug.Print(Num(Foo));
|
||||||
|
|
||||||
TFunction<void(int32)> AddDisplay2 = [Foo](int32 A) { Foo.F(A); };
|
TFunction<void(int32)> AddDisplay2 = [Foo](int32 A) { Foo.F(A); };
|
||||||
AddDisplay2(2);
|
AddDisplay2(2);
|
||||||
@ -1326,21 +1334,21 @@ void TestFunction()
|
|||||||
return Fac(N);
|
return Fac(N);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int32 I = 5; I < 8; ++I) FunctionDebug.Print(Factorial(I));
|
for (int32 I = 5; I < 8; ++I) GFunctionDebug.Print(Factorial(I));
|
||||||
|
|
||||||
always_check(FunctionDebug.Index == 12);
|
always_check(GFunctionDebug.Index == 12);
|
||||||
always_check(FunctionDebug.Output[0] == -9);
|
always_check(GFunctionDebug.Output[0] == -9);
|
||||||
always_check(FunctionDebug.Output[1] == 42);
|
always_check(GFunctionDebug.Output[1] == 42);
|
||||||
always_check(FunctionDebug.Output[2] == 31337);
|
always_check(GFunctionDebug.Output[2] == 31337);
|
||||||
always_check(FunctionDebug.Output[3] == 314160);
|
always_check(GFunctionDebug.Output[3] == 314160);
|
||||||
always_check(FunctionDebug.Output[4] == 314160);
|
always_check(GFunctionDebug.Output[4] == 314160);
|
||||||
always_check(FunctionDebug.Output[5] == 314159);
|
always_check(GFunctionDebug.Output[5] == 314159);
|
||||||
always_check(FunctionDebug.Output[6] == 314161);
|
always_check(GFunctionDebug.Output[6] == 314161);
|
||||||
always_check(FunctionDebug.Output[7] == 314162);
|
always_check(GFunctionDebug.Output[7] == 314162);
|
||||||
always_check(FunctionDebug.Output[8] == 18);
|
always_check(GFunctionDebug.Output[8] == 18);
|
||||||
always_check(FunctionDebug.Output[9] == 120);
|
always_check(GFunctionDebug.Output[9] == 120);
|
||||||
always_check(FunctionDebug.Output[10] == 720);
|
always_check(GFunctionDebug.Output[10] == 720);
|
||||||
always_check(FunctionDebug.Output[11] == 5040);
|
always_check(GFunctionDebug.Output[11] == 5040);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@ NAMESPACE_BEGIN(Testing)
|
|||||||
|
|
||||||
NAMESPACE_UNNAMED_BEGIN
|
NAMESPACE_UNNAMED_BEGIN
|
||||||
|
|
||||||
int32 TestObject;
|
int32 GTestObject;
|
||||||
void TestFunction() { }
|
void TestFunction() { }
|
||||||
|
|
||||||
struct FTestStructA { };
|
struct FTestStructA { };
|
||||||
|
@ -27,41 +27,41 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
using AllocatorType = Allocator;
|
using FAllocatorType = Allocator;
|
||||||
|
|
||||||
using Reference = T&;
|
using FReference = T&;
|
||||||
using ConstReference = const T&;
|
using FConstReference = const T&;
|
||||||
|
|
||||||
using Iterator = TIteratorImpl<false>;
|
using FIterator = TIteratorImpl<false>;
|
||||||
using ConstIterator = TIteratorImpl<true >;
|
using FConstIterator = TIteratorImpl<true >;
|
||||||
|
|
||||||
using ReverseIterator = TReverseIterator< Iterator>;
|
using FReverseIterator = TReverseIterator< FIterator>;
|
||||||
using ConstReverseIterator = TReverseIterator<ConstIterator>;
|
using FConstReverseIterator = TReverseIterator<FConstIterator>;
|
||||||
|
|
||||||
static_assert(CContiguousIterator< Iterator>);
|
static_assert(CContiguousIterator< FIterator>);
|
||||||
static_assert(CContiguousIterator<ConstIterator>);
|
static_assert(CContiguousIterator<FConstIterator>);
|
||||||
|
|
||||||
/** Default constructor. Constructs an empty container with a default-constructed allocator. */
|
/** Default constructor. Constructs an empty container with a default-constructed allocator. */
|
||||||
FORCEINLINE TArray() : TArray(0) { }
|
FORCEINLINE TArray() : TArray(0) { }
|
||||||
|
|
||||||
/** Constructs the container with 'Count' default instances of T. */
|
/** Constructs the container with 'Count' default instances of T. */
|
||||||
explicit TArray(size_t Count) requires (CDefaultConstructible<ElementType>)
|
explicit TArray(size_t Count) requires (CDefaultConstructible<FElementType>)
|
||||||
{
|
{
|
||||||
Impl.ArrayNum = Count;
|
Impl.ArrayNum = Count;
|
||||||
Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
|
Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::DefaultConstruct<ElementType>(Impl.Pointer, Num());
|
Memory::DefaultConstruct<FElementType>(Impl.Pointer, Num());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs the container with 'Count' copies of elements with 'InValue'. */
|
/** Constructs the container with 'Count' copies of elements with 'InValue'. */
|
||||||
TArray(size_t Count, const ElementType& InValue) requires (CCopyConstructible<ElementType>)
|
TArray(size_t Count, const FElementType& InValue) requires (CCopyConstructible<FElementType>)
|
||||||
: TArray(MakeCountedConstantIterator(InValue, Count), DefaultSentinel)
|
: TArray(MakeCountedConstantIterator(InValue, Count), DefaultSentinel)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** Constructs the container with the contents of the range ['First', 'Last'). */
|
/** Constructs the container with the contents of the range ['First', 'Last'). */
|
||||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>> && CMovable<ElementType>)
|
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>> && CMovable<FElementType>)
|
||||||
TArray(I First, S Last)
|
TArray(I First, S Last)
|
||||||
{
|
{
|
||||||
if constexpr (CForwardIterator<I>)
|
if constexpr (CForwardIterator<I>)
|
||||||
@ -76,7 +76,7 @@ public:
|
|||||||
|
|
||||||
for (size_t Index = 0; Index != Count; ++Index)
|
for (size_t Index = 0; Index != Count; ++Index)
|
||||||
{
|
{
|
||||||
new (Impl.Pointer + Index) ElementType(*First++);
|
new (Impl.Pointer + Index) FElementType(*First++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -94,17 +94,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Copy constructor. Constructs the container with the copy of the contents of 'InValue'. */
|
/** Copy constructor. Constructs the container with the copy of the contents of 'InValue'. */
|
||||||
TArray(const TArray& InValue) requires (CCopyConstructible<ElementType>)
|
TArray(const TArray& InValue) requires (CCopyConstructible<FElementType>)
|
||||||
{
|
{
|
||||||
Impl.ArrayNum = InValue.Num();
|
Impl.ArrayNum = InValue.Num();
|
||||||
Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
|
Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::CopyConstruct<ElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
|
Memory::CopyConstruct<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Move constructor. After the move, 'InValue' is guaranteed to be empty. */
|
/** Move constructor. After the move, 'InValue' is guaranteed to be empty. */
|
||||||
TArray(TArray&& InValue) requires (CMoveConstructible<ElementType>)
|
TArray(TArray&& InValue) requires (CMoveConstructible<FElementType>)
|
||||||
{
|
{
|
||||||
Impl.ArrayNum = InValue.Num();
|
Impl.ArrayNum = InValue.Num();
|
||||||
|
|
||||||
@ -122,14 +122,14 @@ public:
|
|||||||
Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
|
Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
|
||||||
}
|
}
|
||||||
|
|
||||||
InValue.Reset();
|
InValue.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs the container with the contents of the initializer list. */
|
/** Constructs the container with the contents of the initializer list. */
|
||||||
FORCEINLINE TArray(initializer_list<ElementType> IL) requires (CCopyConstructible<ElementType>) : TArray(Iteration::Begin(IL), Iteration::End(IL)) { }
|
FORCEINLINE TArray(initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) : TArray(Iteration::Begin(IL), Iteration::End(IL)) { }
|
||||||
|
|
||||||
/** Destructs the array. The destructors of the elements are called and the used storage is deallocated. */
|
/** Destructs the array. The destructors of the elements are called and the used storage is deallocated. */
|
||||||
~TArray()
|
~TArray()
|
||||||
@ -139,7 +139,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Copy assignment operator. Replaces the contents with a copy of the contents of 'InValue'. */
|
/** Copy assignment operator. Replaces the contents with a copy of the contents of 'InValue'. */
|
||||||
TArray& operator=(const TArray& InValue) requires (CCopyable<ElementType>)
|
TArray& operator=(const TArray& InValue) requires (CCopyable<FElementType>)
|
||||||
{
|
{
|
||||||
if (&InValue == this) UNLIKELY return *this;
|
if (&InValue == this) UNLIKELY return *this;
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ public:
|
|||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::CopyConstruct<ElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
|
Memory::CopyConstruct<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -170,7 +170,7 @@ public:
|
|||||||
else if (InValue.Num() <= Max())
|
else if (InValue.Num() <= Max())
|
||||||
{
|
{
|
||||||
Memory::CopyAssign(Impl.Pointer, InValue.Impl.Pointer, Num());
|
Memory::CopyAssign(Impl.Pointer, InValue.Impl.Pointer, Num());
|
||||||
Memory::CopyConstruct<ElementType>(Impl.Pointer + Num(), InValue.Impl.Pointer + Num(), InValue.Num() - Num());
|
Memory::CopyConstruct<FElementType>(Impl.Pointer + Num(), InValue.Impl.Pointer + Num(), InValue.Num() - Num());
|
||||||
}
|
}
|
||||||
else check_no_entry();
|
else check_no_entry();
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Move assignment operator. After the move, 'InValue' is guaranteed to be empty. */
|
/** Move assignment operator. After the move, 'InValue' is guaranteed to be empty. */
|
||||||
TArray& operator=(TArray&& InValue) requires (CMovable<ElementType>)
|
TArray& operator=(TArray&& InValue) requires (CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
if (&InValue == this) UNLIKELY return *this;
|
if (&InValue == this) UNLIKELY return *this;
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ public:
|
|||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, InValue.Impl.Pointer, Num());
|
||||||
|
|
||||||
InValue.Reset();
|
InValue.Reset();
|
||||||
|
|
||||||
@ -229,7 +229,7 @@ public:
|
|||||||
else if (InValue.Num() <= Max())
|
else if (InValue.Num() <= Max())
|
||||||
{
|
{
|
||||||
Memory::MoveAssign(Impl.Pointer, InValue.Impl.Pointer, Num());
|
Memory::MoveAssign(Impl.Pointer, InValue.Impl.Pointer, Num());
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer + Num(), InValue.Impl.Pointer + Num(), InValue.Num() - Num());
|
Memory::MoveConstruct<FElementType>(Impl.Pointer + Num(), InValue.Impl.Pointer + Num(), InValue.Num() - Num());
|
||||||
}
|
}
|
||||||
else check_no_entry();
|
else check_no_entry();
|
||||||
|
|
||||||
@ -241,7 +241,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Replaces the contents with those identified by initializer list. */
|
/** Replaces the contents with those identified by initializer list. */
|
||||||
TArray& operator=(initializer_list<ElementType> IL) requires (CCopyable<ElementType>)
|
TArray& operator=(initializer_list<FElementType> IL) requires (CCopyable<FElementType>)
|
||||||
{
|
{
|
||||||
size_t NumToAllocate = GetNum(IL);
|
size_t NumToAllocate = GetNum(IL);
|
||||||
|
|
||||||
@ -257,7 +257,7 @@ public:
|
|||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::CopyConstruct<ElementType>(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), Num());
|
Memory::CopyConstruct<FElementType>(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), Num());
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -270,7 +270,7 @@ public:
|
|||||||
else if (GetNum(IL) <= Max())
|
else if (GetNum(IL) <= Max())
|
||||||
{
|
{
|
||||||
Memory::CopyAssign(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), Num());
|
Memory::CopyAssign(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), Num());
|
||||||
Memory::CopyConstruct<ElementType>(Impl.Pointer + Num(), NAMESPACE_REDCRAFT::GetData(IL) + Num(), GetNum(IL) - Num());
|
Memory::CopyConstruct<FElementType>(Impl.Pointer + Num(), NAMESPACE_REDCRAFT::GetData(IL) + Num(), GetNum(IL) - Num());
|
||||||
}
|
}
|
||||||
else check_no_entry();
|
else check_no_entry();
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Compares the contents of two arrays. */
|
/** Compares the contents of two arrays. */
|
||||||
NODISCARD friend bool operator==(const TArray& LHS, const TArray& RHS) requires (CWeaklyEqualityComparable<ElementType>)
|
NODISCARD friend bool operator==(const TArray& LHS, const TArray& RHS) requires (CWeaklyEqualityComparable<FElementType>)
|
||||||
{
|
{
|
||||||
if (LHS.Num() != RHS.Num()) return false;
|
if (LHS.Num() != RHS.Num()) return false;
|
||||||
|
|
||||||
@ -293,7 +293,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
||||||
NODISCARD friend auto operator<=>(const TArray& LHS, const TArray& RHS) requires (CSynthThreeWayComparable<ElementType>)
|
NODISCARD friend auto operator<=>(const TArray& LHS, const TArray& RHS) requires (CSynthThreeWayComparable<FElementType>)
|
||||||
{
|
{
|
||||||
const size_t NumToCompare = LHS.Num() < RHS.Num() ? LHS.Num() : RHS.Num();
|
const size_t NumToCompare = LHS.Num() < RHS.Num() ? LHS.Num() : RHS.Num();
|
||||||
|
|
||||||
@ -306,7 +306,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts 'InValue' before 'Iter' in the container. */
|
/** Inserts 'InValue' before 'Iter' in the container. */
|
||||||
Iterator Insert(ConstIterator Iter, const ElementType& InValue) requires (CCopyable<ElementType>)
|
FIterator Insert(FConstIterator Iter, const FElementType& InValue) requires (CCopyable<FElementType>)
|
||||||
{
|
{
|
||||||
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -318,26 +318,26 @@ public:
|
|||||||
|
|
||||||
if (NumToAllocate != Max())
|
if (NumToAllocate != Max())
|
||||||
{
|
{
|
||||||
ElementType* OldAllocation = Impl.Pointer;
|
FElementType* OldAllocation = Impl.Pointer;
|
||||||
const size_t NumToDestruct = Num();
|
const size_t NumToDestruct = Num();
|
||||||
|
|
||||||
Impl.ArrayNum = Num() + 1;
|
Impl.ArrayNum = Num() + 1;
|
||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, InsertIndex);
|
||||||
new (Impl.Pointer + InsertIndex) ElementType(InValue);
|
new (Impl.Pointer + InsertIndex) FElementType(InValue);
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
|
||||||
|
|
||||||
Memory::Destruct(OldAllocation, NumToDestruct);
|
Memory::Destruct(OldAllocation, NumToDestruct);
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + InsertIndex);
|
return FIterator(this, Impl.Pointer + InsertIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InsertIndex != Num())
|
if (InsertIndex != Num())
|
||||||
{
|
{
|
||||||
new (Impl.Pointer + Num()) ElementType(MoveTemp(Impl.Pointer[Num() - 1]));
|
new (Impl.Pointer + Num()) FElementType(MoveTemp(Impl.Pointer[Num() - 1]));
|
||||||
|
|
||||||
for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
|
for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
|
||||||
{
|
{
|
||||||
@ -346,15 +346,15 @@ public:
|
|||||||
|
|
||||||
Impl.Pointer[InsertIndex] = InValue;
|
Impl.Pointer[InsertIndex] = InValue;
|
||||||
}
|
}
|
||||||
else new (Impl.Pointer + Num()) ElementType(InValue);
|
else new (Impl.Pointer + Num()) FElementType(InValue);
|
||||||
|
|
||||||
Impl.ArrayNum = Num() + 1;
|
Impl.ArrayNum = Num() + 1;
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + InsertIndex);
|
return FIterator(this, Impl.Pointer + InsertIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts 'InValue' before 'Iter' in the container. */
|
/** Inserts 'InValue' before 'Iter' in the container. */
|
||||||
Iterator Insert(ConstIterator Iter, ElementType&& InValue) requires (CMovable<ElementType>)
|
FIterator Insert(FConstIterator Iter, FElementType&& InValue) requires (CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -366,26 +366,26 @@ public:
|
|||||||
|
|
||||||
if (NumToAllocate != Max())
|
if (NumToAllocate != Max())
|
||||||
{
|
{
|
||||||
ElementType* OldAllocation = Impl.Pointer;
|
FElementType* OldAllocation = Impl.Pointer;
|
||||||
const size_t NumToDestruct = Num();
|
const size_t NumToDestruct = Num();
|
||||||
|
|
||||||
Impl.ArrayNum = Num() + 1;
|
Impl.ArrayNum = Num() + 1;
|
||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, InsertIndex);
|
||||||
new (Impl.Pointer + InsertIndex) ElementType(MoveTemp(InValue));
|
new (Impl.Pointer + InsertIndex) FElementType(MoveTemp(InValue));
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
|
||||||
|
|
||||||
Memory::Destruct(OldAllocation, NumToDestruct);
|
Memory::Destruct(OldAllocation, NumToDestruct);
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + InsertIndex);
|
return FIterator(this, Impl.Pointer + InsertIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InsertIndex != Num())
|
if (InsertIndex != Num())
|
||||||
{
|
{
|
||||||
new (Impl.Pointer + Num()) ElementType(MoveTemp(Impl.Pointer[Num() - 1]));
|
new (Impl.Pointer + Num()) FElementType(MoveTemp(Impl.Pointer[Num() - 1]));
|
||||||
|
|
||||||
for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
|
for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
|
||||||
{
|
{
|
||||||
@ -394,15 +394,15 @@ public:
|
|||||||
|
|
||||||
Impl.Pointer[InsertIndex] = MoveTemp(InValue);
|
Impl.Pointer[InsertIndex] = MoveTemp(InValue);
|
||||||
}
|
}
|
||||||
else new (Impl.Pointer + Num()) ElementType(MoveTemp(InValue));
|
else new (Impl.Pointer + Num()) FElementType(MoveTemp(InValue));
|
||||||
|
|
||||||
Impl.ArrayNum = Num() + 1;
|
Impl.ArrayNum = Num() + 1;
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + InsertIndex);
|
return FIterator(this, Impl.Pointer + InsertIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts 'Count' copies of the 'InValue' before 'Iter' in the container. */
|
/** Inserts 'Count' copies of the 'InValue' before 'Iter' in the container. */
|
||||||
Iterator Insert(ConstIterator Iter, size_t Count, const ElementType& InValue) requires (CCopyable<ElementType>)
|
FIterator Insert(FConstIterator Iter, size_t Count, const FElementType& InValue) requires (CCopyable<FElementType>)
|
||||||
{
|
{
|
||||||
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -410,9 +410,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts elements from range ['First', 'Last') before 'Iter'. */
|
/** Inserts elements from range ['First', 'Last') before 'Iter'. */
|
||||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>
|
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>
|
||||||
&& CAssignableFrom<ElementType&, TIteratorReferenceType<I>> && CMovable<ElementType>)
|
&& CAssignableFrom<FElementType&, TIteratorReferenceType<I>> && CMovable<FElementType>)
|
||||||
Iterator Insert(ConstIterator Iter, I First, S Last)
|
FIterator Insert(FConstIterator Iter, I First, S Last)
|
||||||
{
|
{
|
||||||
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -423,7 +423,7 @@ public:
|
|||||||
const size_t InsertIndex = Iter - Begin();
|
const size_t InsertIndex = Iter - Begin();
|
||||||
const size_t Count = Iteration::Distance(First, Last);
|
const size_t Count = Iteration::Distance(First, Last);
|
||||||
|
|
||||||
if (Count == 0) return Iterator(this, Impl.Pointer + InsertIndex);
|
if (Count == 0) return FIterator(this, Impl.Pointer + InsertIndex);
|
||||||
|
|
||||||
const size_t NumToAllocate = Num() + Count > Max() ? Impl->CalculateSlackGrow(Num() + Count, Max()) : Max();
|
const size_t NumToAllocate = Num() + Count > Max() ? Impl->CalculateSlackGrow(Num() + Count, Max()) : Max();
|
||||||
|
|
||||||
@ -431,26 +431,26 @@ public:
|
|||||||
|
|
||||||
if (NumToAllocate != Max())
|
if (NumToAllocate != Max())
|
||||||
{
|
{
|
||||||
ElementType* OldAllocation = Impl.Pointer;
|
FElementType* OldAllocation = Impl.Pointer;
|
||||||
const size_t NumToDestruct = Num();
|
const size_t NumToDestruct = Num();
|
||||||
|
|
||||||
Impl.ArrayNum = Num() + Count;
|
Impl.ArrayNum = Num() + Count;
|
||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, InsertIndex);
|
||||||
|
|
||||||
for (size_t Index = InsertIndex; Index != InsertIndex + Count; ++Index)
|
for (size_t Index = InsertIndex; Index != InsertIndex + Count; ++Index)
|
||||||
{
|
{
|
||||||
new (Impl.Pointer + Index) ElementType(*First++);
|
new (Impl.Pointer + Index) FElementType(*First++);
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + Count, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + Count, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
|
||||||
|
|
||||||
Memory::Destruct(OldAllocation, NumToDestruct);
|
Memory::Destruct(OldAllocation, NumToDestruct);
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + InsertIndex);
|
return FIterator(this, Impl.Pointer + InsertIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -492,7 +492,7 @@ public:
|
|||||||
|
|
||||||
for (size_t TargetIndex = IndexO - 1; TargetIndex != IndexD - 1; --TargetIndex)
|
for (size_t TargetIndex = IndexO - 1; TargetIndex != IndexD - 1; --TargetIndex)
|
||||||
{
|
{
|
||||||
new (Impl.Pointer + TargetIndex) ElementType(MoveTemp(Impl.Pointer[TargetIndex - Count]));
|
new (Impl.Pointer + TargetIndex) FElementType(MoveTemp(Impl.Pointer[TargetIndex - Count]));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t TargetIndex = IndexD - 1; TargetIndex != IndexC - 1; --TargetIndex)
|
for (size_t TargetIndex = IndexD - 1; TargetIndex != IndexC - 1; --TargetIndex)
|
||||||
@ -507,14 +507,14 @@ public:
|
|||||||
|
|
||||||
for (size_t TargetIndex = IndexB; TargetIndex != IndexC; ++TargetIndex)
|
for (size_t TargetIndex = IndexB; TargetIndex != IndexC; ++TargetIndex)
|
||||||
{
|
{
|
||||||
new (Impl.Pointer + TargetIndex) ElementType(*First++);
|
new (Impl.Pointer + TargetIndex) FElementType(*First++);
|
||||||
}
|
}
|
||||||
|
|
||||||
check(First == Last);
|
check(First == Last);
|
||||||
|
|
||||||
Impl.ArrayNum = Num() + Count;
|
Impl.ArrayNum = Num() + Count;
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + InsertIndex);
|
return FIterator(this, Impl.Pointer + InsertIndex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -524,14 +524,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts elements from initializer list before 'Iter' in the container. */
|
/** Inserts elements from initializer list before 'Iter' in the container. */
|
||||||
FORCEINLINE Iterator Insert(ConstIterator Iter, initializer_list<ElementType> IL) requires (CCopyable<ElementType>)
|
FORCEINLINE FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL) requires (CCopyable<FElementType>)
|
||||||
{
|
{
|
||||||
return Insert(Iter, Iteration::Begin(IL), Iteration::End(IL));
|
return Insert(Iter, Iteration::Begin(IL), Iteration::End(IL));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts a new element into the container directly before 'Iter'. */
|
/** Inserts a new element into the container directly before 'Iter'. */
|
||||||
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...> && CMovable<ElementType>)
|
template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...> && CMovable<FElementType>)
|
||||||
Iterator Emplace(ConstIterator Iter, Ts&&... Args)
|
FIterator Emplace(FConstIterator Iter, Ts&&... Args)
|
||||||
{
|
{
|
||||||
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -543,43 +543,43 @@ public:
|
|||||||
|
|
||||||
if (NumToAllocate != Max())
|
if (NumToAllocate != Max())
|
||||||
{
|
{
|
||||||
ElementType* OldAllocation = Impl.Pointer;
|
FElementType* OldAllocation = Impl.Pointer;
|
||||||
const size_t NumToDestruct = Num();
|
const size_t NumToDestruct = Num();
|
||||||
|
|
||||||
Impl.ArrayNum = Num() + 1;
|
Impl.ArrayNum = Num() + 1;
|
||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, InsertIndex);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, InsertIndex);
|
||||||
new (Impl.Pointer + InsertIndex) ElementType(Forward<Ts>(Args)...);
|
new (Impl.Pointer + InsertIndex) FElementType(Forward<Ts>(Args)...);
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer + InsertIndex + 1, OldAllocation + InsertIndex, NumToDestruct - InsertIndex);
|
||||||
|
|
||||||
Memory::Destruct(OldAllocation, NumToDestruct);
|
Memory::Destruct(OldAllocation, NumToDestruct);
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + InsertIndex);
|
return FIterator(this, Impl.Pointer + InsertIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InsertIndex != Num())
|
if (InsertIndex != Num())
|
||||||
{
|
{
|
||||||
new (Impl.Pointer + Num()) ElementType(MoveTemp(Impl.Pointer[Num() - 1]));
|
new (Impl.Pointer + Num()) FElementType(MoveTemp(Impl.Pointer[Num() - 1]));
|
||||||
|
|
||||||
for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
|
for (size_t Index = Num() - 1; Index != InsertIndex; --Index)
|
||||||
{
|
{
|
||||||
Impl.Pointer[Index] = MoveTemp(Impl.Pointer[Index - 1]);
|
Impl.Pointer[Index] = MoveTemp(Impl.Pointer[Index - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Impl.Pointer[InsertIndex] = ElementType(Forward<Ts>(Args)...);
|
Impl.Pointer[InsertIndex] = FElementType(Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
else new (Impl.Pointer + Num()) ElementType(Forward<Ts>(Args)...);
|
else new (Impl.Pointer + Num()) FElementType(Forward<Ts>(Args)...);
|
||||||
|
|
||||||
Impl.ArrayNum = Num() + 1;
|
Impl.ArrayNum = Num() + 1;
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + InsertIndex);
|
return FIterator(this, Impl.Pointer + InsertIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes the element at 'Iter' in the container. Without changing the order of elements. */
|
/** Removes the element at 'Iter' in the container. Without changing the order of elements. */
|
||||||
FORCEINLINE Iterator StableErase(ConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<ElementType>)
|
FORCEINLINE FIterator StableErase(FConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
checkf(IsValidIterator(Iter) && Iter != End(), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(IsValidIterator(Iter) && Iter != End(), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -587,33 +587,33 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Removes the elements in the range ['First', 'Last') in the container. Without changing the order of elements. */
|
/** Removes the elements in the range ['First', 'Last') in the container. Without changing the order of elements. */
|
||||||
Iterator StableErase(ConstIterator First, ConstIterator Last, bool bAllowShrinking = true) requires (CMovable<ElementType>)
|
FIterator StableErase(FConstIterator First, FConstIterator Last, bool bAllowShrinking = true) requires (CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
checkf(IsValidIterator(First) && IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(IsValidIterator(First) && IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
const size_t EraseIndex = First - Begin();
|
const size_t EraseIndex = First - Begin();
|
||||||
const size_t EraseCount = Last - First;
|
const size_t EraseCount = Last - First;
|
||||||
|
|
||||||
if (EraseCount == 0) return Iterator(this, Impl.Pointer + EraseIndex);
|
if (EraseCount == 0) return FIterator(this, Impl.Pointer + EraseIndex);
|
||||||
|
|
||||||
const size_t NumToAllocate = bAllowShrinking ? Impl->CalculateSlackShrink(Num() - EraseCount, Max()) : Max();
|
const size_t NumToAllocate = bAllowShrinking ? Impl->CalculateSlackShrink(Num() - EraseCount, Max()) : Max();
|
||||||
|
|
||||||
if (NumToAllocate != Max())
|
if (NumToAllocate != Max())
|
||||||
{
|
{
|
||||||
ElementType* OldAllocation = Impl.Pointer;
|
FElementType* OldAllocation = Impl.Pointer;
|
||||||
const size_t NumToDestruct = Num();
|
const size_t NumToDestruct = Num();
|
||||||
|
|
||||||
Impl.ArrayNum = Num() - EraseCount;
|
Impl.ArrayNum = Num() - EraseCount;
|
||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, EraseIndex);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, EraseIndex);
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
|
||||||
|
|
||||||
Memory::Destruct(OldAllocation, NumToDestruct);
|
Memory::Destruct(OldAllocation, NumToDestruct);
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + EraseIndex);
|
return FIterator(this, Impl.Pointer + EraseIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t Index = EraseIndex + EraseCount; Index != Num(); ++Index)
|
for (size_t Index = EraseIndex + EraseCount; Index != Num(); ++Index)
|
||||||
@ -625,11 +625,11 @@ public:
|
|||||||
|
|
||||||
Impl.ArrayNum = Num() - EraseCount;
|
Impl.ArrayNum = Num() - EraseCount;
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + EraseIndex);
|
return FIterator(this, Impl.Pointer + EraseIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes the element at 'Iter' in the container. But it may change the order of elements. */
|
/** Removes the element at 'Iter' in the container. But it may change the order of elements. */
|
||||||
FORCEINLINE Iterator Erase(ConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<ElementType>)
|
FORCEINLINE FIterator Erase(FConstIterator Iter, bool bAllowShrinking = true) requires (CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
checkf(IsValidIterator(Iter) && Iter != End(), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(IsValidIterator(Iter) && Iter != End(), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -637,33 +637,33 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Removes the elements in the range ['First', 'Last') in the container. But it may change the order of elements. */
|
/** Removes the elements in the range ['First', 'Last') in the container. But it may change the order of elements. */
|
||||||
Iterator Erase(ConstIterator First, ConstIterator Last, bool bAllowShrinking = true) requires (CMovable<ElementType>)
|
FIterator Erase(FConstIterator First, FConstIterator Last, bool bAllowShrinking = true) requires (CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
checkf(IsValidIterator(First) && IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(IsValidIterator(First) && IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
const size_t EraseIndex = First - Begin();
|
const size_t EraseIndex = First - Begin();
|
||||||
const size_t EraseCount = Last - First;
|
const size_t EraseCount = Last - First;
|
||||||
|
|
||||||
if (EraseCount == 0) return Iterator(this, Impl.Pointer + EraseIndex);
|
if (EraseCount == 0) return FIterator(this, Impl.Pointer + EraseIndex);
|
||||||
|
|
||||||
const size_t NumToAllocate = bAllowShrinking ? Impl->CalculateSlackShrink(Num() - EraseCount, Max()) : Max();
|
const size_t NumToAllocate = bAllowShrinking ? Impl->CalculateSlackShrink(Num() - EraseCount, Max()) : Max();
|
||||||
|
|
||||||
if (NumToAllocate != Max())
|
if (NumToAllocate != Max())
|
||||||
{
|
{
|
||||||
ElementType* OldAllocation = Impl.Pointer;
|
FElementType* OldAllocation = Impl.Pointer;
|
||||||
const size_t NumToDestruct = Num();
|
const size_t NumToDestruct = Num();
|
||||||
|
|
||||||
Impl.ArrayNum = Num() - EraseCount;
|
Impl.ArrayNum = Num() - EraseCount;
|
||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, EraseIndex);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, EraseIndex);
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer + EraseIndex, OldAllocation + EraseIndex + EraseCount, NumToDestruct - EraseIndex - EraseCount);
|
||||||
|
|
||||||
Memory::Destruct(OldAllocation, NumToDestruct);
|
Memory::Destruct(OldAllocation, NumToDestruct);
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + EraseIndex);
|
return FIterator(this, Impl.Pointer + EraseIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t Index = 0; Index != EraseCount; ++Index)
|
for (size_t Index = 0; Index != EraseCount; ++Index)
|
||||||
@ -677,24 +677,24 @@ public:
|
|||||||
|
|
||||||
Impl.ArrayNum = Num() - EraseCount;
|
Impl.ArrayNum = Num() - EraseCount;
|
||||||
|
|
||||||
return Iterator(this, Impl.Pointer + EraseIndex);
|
return FIterator(this, Impl.Pointer + EraseIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Appends the given element value to the end of the container. */
|
/** Appends the given element value to the end of the container. */
|
||||||
FORCEINLINE void PushBack(const ElementType& InValue) requires (CCopyable<ElementType>)
|
FORCEINLINE void PushBack(const FElementType& InValue) requires (CCopyable<FElementType>)
|
||||||
{
|
{
|
||||||
EmplaceBack(InValue);
|
EmplaceBack(InValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Appends the given element value to the end of the container. */
|
/** Appends the given element value to the end of the container. */
|
||||||
FORCEINLINE void PushBack(ElementType&& InValue) requires (CMovable<ElementType>)
|
FORCEINLINE void PushBack(FElementType&& InValue) requires (CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
EmplaceBack(MoveTemp(InValue));
|
EmplaceBack(MoveTemp(InValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Appends a new element to the end of the container. */
|
/** Appends a new element to the end of the container. */
|
||||||
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...> && CMovable<ElementType>)
|
template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...> && CMovable<FElementType>)
|
||||||
ElementType& EmplaceBack(Ts&&... Args)
|
FElementType& EmplaceBack(Ts&&... Args)
|
||||||
{
|
{
|
||||||
const size_t NumToAllocate = Num() + 1 > Max() ? Impl->CalculateSlackGrow(Num() + 1, Max()) : Max();
|
const size_t NumToAllocate = Num() + 1 > Max() ? Impl->CalculateSlackGrow(Num() + 1, Max()) : Max();
|
||||||
|
|
||||||
@ -702,15 +702,15 @@ public:
|
|||||||
|
|
||||||
if (NumToAllocate != Max())
|
if (NumToAllocate != Max())
|
||||||
{
|
{
|
||||||
ElementType* OldAllocation = Impl.Pointer;
|
FElementType* OldAllocation = Impl.Pointer;
|
||||||
const size_t NumToDestruct = Num();
|
const size_t NumToDestruct = Num();
|
||||||
|
|
||||||
Impl.ArrayNum = Num() + 1;
|
Impl.ArrayNum = Num() + 1;
|
||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num() - 1);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num() - 1);
|
||||||
new (Impl.Pointer + Num() - 1) ElementType(Forward<Ts>(Args)...);
|
new (Impl.Pointer + Num() - 1) FElementType(Forward<Ts>(Args)...);
|
||||||
|
|
||||||
Memory::Destruct(OldAllocation, NumToDestruct);
|
Memory::Destruct(OldAllocation, NumToDestruct);
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
@ -718,7 +718,7 @@ public:
|
|||||||
return Impl.Pointer[Num() - 1];
|
return Impl.Pointer[Num() - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
new (Impl.Pointer + Num()) ElementType(Forward<Ts>(Args)...);
|
new (Impl.Pointer + Num()) FElementType(Forward<Ts>(Args)...);
|
||||||
|
|
||||||
Impl.ArrayNum = Num() + 1;
|
Impl.ArrayNum = Num() + 1;
|
||||||
|
|
||||||
@ -726,13 +726,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Removes the last element of the container. The array cannot be empty. */
|
/** Removes the last element of the container. The array cannot be empty. */
|
||||||
FORCEINLINE void PopBack(bool bAllowShrinking = true) requires (CMovable<ElementType>)
|
FORCEINLINE void PopBack(bool bAllowShrinking = true) requires (CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
Erase(End() - 1, bAllowShrinking);
|
Erase(End() - 1, bAllowShrinking);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Resizes the container to contain 'Count' elements. Additional default elements are appended. */
|
/** Resizes the container to contain 'Count' elements. Additional default elements are appended. */
|
||||||
void SetNum(size_t Count, bool bAllowShrinking = true) requires (CDefaultConstructible<ElementType> && CMovable<ElementType>)
|
void SetNum(size_t Count, bool bAllowShrinking = true) requires (CDefaultConstructible<FElementType> && CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
size_t NumToAllocate = Count;
|
size_t NumToAllocate = Count;
|
||||||
|
|
||||||
@ -741,7 +741,7 @@ public:
|
|||||||
|
|
||||||
if (NumToAllocate != Max())
|
if (NumToAllocate != Max())
|
||||||
{
|
{
|
||||||
ElementType* OldAllocation = Impl.Pointer;
|
FElementType* OldAllocation = Impl.Pointer;
|
||||||
const size_t NumToDestruct = Num();
|
const size_t NumToDestruct = Num();
|
||||||
|
|
||||||
Impl.ArrayNum = Count;
|
Impl.ArrayNum = Count;
|
||||||
@ -750,12 +750,12 @@ public:
|
|||||||
|
|
||||||
if (NumToDestruct <= Num())
|
if (NumToDestruct <= Num())
|
||||||
{
|
{
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, NumToDestruct);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, NumToDestruct);
|
||||||
Memory::DefaultConstruct<ElementType>(Impl.Pointer + NumToDestruct, Num() - NumToDestruct);
|
Memory::DefaultConstruct<FElementType>(Impl.Pointer + NumToDestruct, Num() - NumToDestruct);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num());
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Destruct(OldAllocation, NumToDestruct);
|
Memory::Destruct(OldAllocation, NumToDestruct);
|
||||||
@ -770,7 +770,7 @@ public:
|
|||||||
}
|
}
|
||||||
else if (Count <= Max())
|
else if (Count <= Max())
|
||||||
{
|
{
|
||||||
Memory::DefaultConstruct<ElementType>(Impl.Pointer + Num(), Count - Num());
|
Memory::DefaultConstruct<FElementType>(Impl.Pointer + Num(), Count - Num());
|
||||||
}
|
}
|
||||||
else check_no_entry();
|
else check_no_entry();
|
||||||
|
|
||||||
@ -778,7 +778,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Resizes the container to contain 'Count' elements. Additional copies of 'InValue' are appended. */
|
/** Resizes the container to contain 'Count' elements. Additional copies of 'InValue' are appended. */
|
||||||
void SetNum(size_t Count, const ElementType& InValue, bool bAllowShrinking = true) requires (CCopyConstructible<ElementType> && CMovable<ElementType>)
|
void SetNum(size_t Count, const FElementType& InValue, bool bAllowShrinking = true) requires (CCopyConstructible<FElementType> && CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
size_t NumToAllocate = Count;
|
size_t NumToAllocate = Count;
|
||||||
|
|
||||||
@ -787,7 +787,7 @@ public:
|
|||||||
|
|
||||||
if (NumToAllocate != Max())
|
if (NumToAllocate != Max())
|
||||||
{
|
{
|
||||||
ElementType* OldAllocation = Impl.Pointer;
|
FElementType* OldAllocation = Impl.Pointer;
|
||||||
const size_t NumToDestruct = Num();
|
const size_t NumToDestruct = Num();
|
||||||
|
|
||||||
Impl.ArrayNum = Count;
|
Impl.ArrayNum = Count;
|
||||||
@ -796,16 +796,16 @@ public:
|
|||||||
|
|
||||||
if (NumToDestruct <= Num())
|
if (NumToDestruct <= Num())
|
||||||
{
|
{
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, NumToDestruct);
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, NumToDestruct);
|
||||||
|
|
||||||
for (size_t Index = NumToDestruct; Index != Num(); ++Index)
|
for (size_t Index = NumToDestruct; Index != Num(); ++Index)
|
||||||
{
|
{
|
||||||
new (Impl.Pointer + Index) ElementType(InValue);
|
new (Impl.Pointer + Index) FElementType(InValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num());
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Destruct(OldAllocation, NumToDestruct);
|
Memory::Destruct(OldAllocation, NumToDestruct);
|
||||||
@ -822,7 +822,7 @@ public:
|
|||||||
{
|
{
|
||||||
for (size_t Index = Num(); Index != Count; ++Index)
|
for (size_t Index = Num(); Index != Count; ++Index)
|
||||||
{
|
{
|
||||||
new (Impl.Pointer + Index) ElementType(InValue);
|
new (Impl.Pointer + Index) FElementType(InValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else check_no_entry();
|
else check_no_entry();
|
||||||
@ -831,19 +831,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Increase the max capacity of the array to a value that's greater or equal to 'Count'. */
|
/** Increase the max capacity of the array to a value that's greater or equal to 'Count'. */
|
||||||
void Reserve(size_t Count) requires (CMovable<ElementType>)
|
void Reserve(size_t Count) requires (CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
if (Count <= Max()) return;
|
if (Count <= Max()) return;
|
||||||
|
|
||||||
const size_t NumToAllocate = Impl->CalculateSlackReserve(Count);
|
const size_t NumToAllocate = Impl->CalculateSlackReserve(Count);
|
||||||
ElementType* OldAllocation = Impl.Pointer;
|
FElementType* OldAllocation = Impl.Pointer;
|
||||||
|
|
||||||
check(NumToAllocate > Max());
|
check(NumToAllocate > Max());
|
||||||
|
|
||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num());
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
|
||||||
|
|
||||||
Memory::Destruct(OldAllocation, Num());
|
Memory::Destruct(OldAllocation, Num());
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
@ -858,32 +858,32 @@ public:
|
|||||||
|
|
||||||
if (NumToAllocate == Max()) return;
|
if (NumToAllocate == Max()) return;
|
||||||
|
|
||||||
ElementType* OldAllocation = Impl.Pointer;
|
FElementType* OldAllocation = Impl.Pointer;
|
||||||
|
|
||||||
Impl.ArrayMax = NumToAllocate;
|
Impl.ArrayMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(Max());
|
Impl.Pointer = Impl->Allocate(Max());
|
||||||
|
|
||||||
Memory::MoveConstruct<ElementType>(Impl.Pointer, OldAllocation, Num());
|
Memory::MoveConstruct<FElementType>(Impl.Pointer, OldAllocation, Num());
|
||||||
Memory::Destruct(OldAllocation, Num());
|
Memory::Destruct(OldAllocation, Num());
|
||||||
|
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The pointer to the underlying element storage. */
|
/** @return The pointer to the underlying element storage. */
|
||||||
NODISCARD FORCEINLINE ElementType* GetData() { return Impl.Pointer; }
|
NODISCARD FORCEINLINE FElementType* GetData() { return Impl.Pointer; }
|
||||||
NODISCARD FORCEINLINE const ElementType* GetData() const { return Impl.Pointer; }
|
NODISCARD FORCEINLINE const FElementType* GetData() const { return Impl.Pointer; }
|
||||||
|
|
||||||
/** @return The iterator to the first or end element. */
|
/** @return The iterator to the first or end element. */
|
||||||
NODISCARD FORCEINLINE Iterator Begin() { return Iterator(this, Impl.Pointer); }
|
NODISCARD FORCEINLINE FIterator Begin() { return FIterator(this, Impl.Pointer); }
|
||||||
NODISCARD FORCEINLINE ConstIterator Begin() const { return ConstIterator(this, Impl.Pointer); }
|
NODISCARD FORCEINLINE FConstIterator Begin() const { return FConstIterator(this, Impl.Pointer); }
|
||||||
NODISCARD FORCEINLINE Iterator End() { return Iterator(this, Impl.Pointer + Num()); }
|
NODISCARD FORCEINLINE FIterator End() { return FIterator(this, Impl.Pointer + Num()); }
|
||||||
NODISCARD FORCEINLINE ConstIterator End() const { return ConstIterator(this, Impl.Pointer + Num()); }
|
NODISCARD FORCEINLINE FConstIterator End() const { return FConstIterator(this, Impl.Pointer + Num()); }
|
||||||
|
|
||||||
/** @return The reverse iterator to the first or end element. */
|
/** @return The reverse iterator to the first or end element. */
|
||||||
NODISCARD FORCEINLINE ReverseIterator RBegin() { return ReverseIterator(End()); }
|
NODISCARD FORCEINLINE FReverseIterator RBegin() { return FReverseIterator(End()); }
|
||||||
NODISCARD FORCEINLINE ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
|
NODISCARD FORCEINLINE FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
|
||||||
NODISCARD FORCEINLINE ReverseIterator REnd() { return ReverseIterator(Begin()); }
|
NODISCARD FORCEINLINE FReverseIterator REnd() { return FReverseIterator(Begin()); }
|
||||||
NODISCARD FORCEINLINE ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); }
|
NODISCARD FORCEINLINE FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
|
||||||
|
|
||||||
/** @return The number of elements in the container. */
|
/** @return The number of elements in the container. */
|
||||||
NODISCARD FORCEINLINE size_t Num() const { return Impl.ArrayNum; }
|
NODISCARD FORCEINLINE size_t Num() const { return Impl.ArrayNum; }
|
||||||
@ -895,17 +895,17 @@ public:
|
|||||||
NODISCARD FORCEINLINE bool IsEmpty() const { return Num() == 0; }
|
NODISCARD FORCEINLINE bool IsEmpty() const { return Num() == 0; }
|
||||||
|
|
||||||
/** @return true if the iterator is valid, false otherwise. */
|
/** @return true if the iterator is valid, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool IsValidIterator(ConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
|
NODISCARD FORCEINLINE bool IsValidIterator(FConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
|
||||||
|
|
||||||
/** @return The reference to the requested element. */
|
/** @return The reference to the requested element. */
|
||||||
NODISCARD FORCEINLINE ElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
|
NODISCARD FORCEINLINE FElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
|
||||||
NODISCARD FORCEINLINE const ElementType& operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
|
NODISCARD FORCEINLINE const FElementType& operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
|
||||||
|
|
||||||
/** @return The reference to the first or last element. */
|
/** @return The reference to the first or last element. */
|
||||||
NODISCARD FORCEINLINE ElementType& Front() { return *Begin(); }
|
NODISCARD FORCEINLINE FElementType& Front() { return *Begin(); }
|
||||||
NODISCARD FORCEINLINE const ElementType& Front() const { return *Begin(); }
|
NODISCARD FORCEINLINE const FElementType& Front() const { return *Begin(); }
|
||||||
NODISCARD FORCEINLINE ElementType& Back() { return *(End() - 1); }
|
NODISCARD FORCEINLINE FElementType& Back() { return *(End() - 1); }
|
||||||
NODISCARD FORCEINLINE const ElementType& Back() const { return *(End() - 1); }
|
NODISCARD FORCEINLINE const FElementType& Back() const { return *(End() - 1); }
|
||||||
|
|
||||||
/** Erases all elements from the container. After this call, Num() returns zero. */
|
/** Erases all elements from the container. After this call, Num() returns zero. */
|
||||||
void Reset(bool bAllowShrinking = true)
|
void Reset(bool bAllowShrinking = true)
|
||||||
@ -929,11 +929,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Overloads the GetTypeHash algorithm for TArray. */
|
/** Overloads the GetTypeHash algorithm for TArray. */
|
||||||
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TArray& A) requires (CHashable<ElementType>)
|
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TArray& A) requires (CHashable<FElementType>)
|
||||||
{
|
{
|
||||||
size_t Result = 0;
|
size_t Result = 0;
|
||||||
|
|
||||||
for (ConstIterator Iter = A.Begin(); Iter != A.End(); ++Iter)
|
for (FConstIterator Iter = A.Begin(); Iter != A.End(); ++Iter)
|
||||||
{
|
{
|
||||||
Result = HashCombine(Result, GetTypeHash(*Iter));
|
Result = HashCombine(Result, GetTypeHash(*Iter));
|
||||||
}
|
}
|
||||||
@ -942,7 +942,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Overloads the Swap algorithm for TArray. */
|
/** Overloads the Swap algorithm for TArray. */
|
||||||
friend void Swap(TArray& A, TArray& B) requires (CMovable<ElementType>)
|
friend void Swap(TArray& A, TArray& B) requires (CMovable<FElementType>)
|
||||||
{
|
{
|
||||||
const bool bIsTransferable =
|
const bool bIsTransferable =
|
||||||
A.Impl->IsTransferable(A.Impl.Pointer) &&
|
A.Impl->IsTransferable(A.Impl.Pointer) &&
|
||||||
@ -966,13 +966,13 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ALLOCATOR_WRAPPER_BEGIN(AllocatorType, ElementType, Impl)
|
ALLOCATOR_WRAPPER_BEGIN(FAllocatorType, FElementType, Impl)
|
||||||
{
|
{
|
||||||
size_t ArrayNum;
|
size_t ArrayNum;
|
||||||
size_t ArrayMax;
|
size_t ArrayMax;
|
||||||
ElementType* Pointer;
|
FElementType* Pointer;
|
||||||
}
|
}
|
||||||
ALLOCATOR_WRAPPER_END(AllocatorType, ElementType, Impl)
|
ALLOCATOR_WRAPPER_END(FAllocatorType, FElementType, Impl)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -981,7 +981,7 @@ private:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TRemoveCV<T>;
|
using FElementType = TRemoveCV<T>;
|
||||||
|
|
||||||
FORCEINLINE TIteratorImpl() = default;
|
FORCEINLINE TIteratorImpl() = default;
|
||||||
|
|
||||||
|
@ -29,15 +29,15 @@ class TArrayView
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
|
|
||||||
using Reference = T&;
|
using FReference = T&;
|
||||||
|
|
||||||
class Iterator;
|
class FIterator;
|
||||||
|
|
||||||
using ReverseIterator = TReverseIterator<Iterator>;
|
using FReverseIterator = TReverseIterator<FIterator>;
|
||||||
|
|
||||||
static_assert(CContiguousIterator<Iterator>);
|
static_assert(CContiguousIterator<FIterator>);
|
||||||
|
|
||||||
static constexpr size_t Extent = InExtent;
|
static constexpr size_t Extent = InExtent;
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs an array view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */
|
/** Constructs an array view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */
|
||||||
template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], ElementType(*)[]>)
|
template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], FElementType(*)[]>)
|
||||||
FORCEINLINE constexpr explicit (Extent != DynamicExtent) TArrayView(I InFirst, size_t InCount)
|
FORCEINLINE constexpr explicit (Extent != DynamicExtent) TArrayView(I InFirst, size_t InCount)
|
||||||
{
|
{
|
||||||
checkf(Extent == DynamicExtent || Extent == InCount, TEXT("Illegal range count. Please check InCount."));
|
checkf(Extent == DynamicExtent || Extent == InCount, TEXT("Illegal range count. Please check InCount."));
|
||||||
@ -67,7 +67,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs an array view that is a view over the range ['InFirst', 'InLast'). */
|
/** Constructs an array view that is a view over the range ['InFirst', 'InLast'). */
|
||||||
template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], ElementType(*)[]>)
|
template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], FElementType(*)[]>)
|
||||||
FORCEINLINE constexpr explicit (Extent != DynamicExtent) TArrayView(I InFirst, S InLast)
|
FORCEINLINE constexpr explicit (Extent != DynamicExtent) TArrayView(I InFirst, S InLast)
|
||||||
{
|
{
|
||||||
checkf(Extent == DynamicExtent || Extent == InLast - InFirst, TEXT("Illegal range iterator. Please check InLast - InFirst."));
|
checkf(Extent == DynamicExtent || Extent == InLast - InFirst, TEXT("Illegal range iterator. Please check InLast - InFirst."));
|
||||||
@ -82,7 +82,7 @@ public:
|
|||||||
|
|
||||||
/** Constructs an array view that is a view over the array 'InArray'. */
|
/** Constructs an array view that is a view over the array 'InArray'. */
|
||||||
template <size_t N> requires (Extent == DynamicExtent || N == Extent)
|
template <size_t N> requires (Extent == DynamicExtent || N == Extent)
|
||||||
FORCEINLINE constexpr TArrayView(ElementType(&InArray)[N])
|
FORCEINLINE constexpr TArrayView(FElementType(&InArray)[N])
|
||||||
{
|
{
|
||||||
Impl.Pointer = InArray;
|
Impl.Pointer = InArray;
|
||||||
|
|
||||||
@ -93,23 +93,23 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs an array view that is a view over the array 'InArray'. */
|
/** Constructs an array view that is a view over the array 'InArray'. */
|
||||||
template <typename U, size_t N> requires (CConvertibleTo<U(*)[], ElementType(*)[]>)
|
template <typename U, size_t N> requires (CConvertibleTo<U(*)[], FElementType(*)[]>)
|
||||||
FORCEINLINE constexpr TArrayView(TStaticArray<U, N>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
|
FORCEINLINE constexpr TArrayView(TStaticArray<U, N>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
|
||||||
|
|
||||||
/** Constructs an array view that is a view over the array 'InArray'. */
|
/** Constructs an array view that is a view over the array 'InArray'. */
|
||||||
template <typename U, size_t N> requires (CConvertibleTo<const U(*)[], ElementType(*)[]>)
|
template <typename U, size_t N> requires (CConvertibleTo<const U(*)[], FElementType(*)[]>)
|
||||||
FORCEINLINE constexpr TArrayView(const TStaticArray<U, N>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
|
FORCEINLINE constexpr TArrayView(const TStaticArray<U, N>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
|
||||||
|
|
||||||
/** Constructs an array view that is a view over the array 'InArray'. */
|
/** Constructs an array view that is a view over the array 'InArray'. */
|
||||||
template <typename U, typename Allocator> requires (CConvertibleTo<U(*)[], ElementType(*)[]>)
|
template <typename U, typename Allocator> requires (CConvertibleTo<U(*)[], FElementType(*)[]>)
|
||||||
FORCEINLINE constexpr TArrayView(TArray<U, Allocator>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
|
FORCEINLINE constexpr TArrayView(TArray<U, Allocator>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
|
||||||
|
|
||||||
/** Constructs an array view that is a view over the array 'InArray'. */
|
/** Constructs an array view that is a view over the array 'InArray'. */
|
||||||
template <typename U, typename Allocator> requires (CConvertibleTo<const U(*)[], ElementType(*)[]>)
|
template <typename U, typename Allocator> requires (CConvertibleTo<const U(*)[], FElementType(*)[]>)
|
||||||
FORCEINLINE constexpr TArrayView(const TArray<U, Allocator>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
|
FORCEINLINE constexpr TArrayView(const TArray<U, Allocator>& InArray) : TArrayView(InArray.GetData(), InArray.Num()) { }
|
||||||
|
|
||||||
/** Converting constructor from another array view 'InValue'. */
|
/** Converting constructor from another array view 'InValue'. */
|
||||||
template <typename U, size_t N> requires ((Extent == DynamicExtent || N == DynamicExtent || N == Extent) && CConvertibleTo<U(*)[], ElementType(*)[]>)
|
template <typename U, size_t N> requires ((Extent == DynamicExtent || N == DynamicExtent || N == Extent) && CConvertibleTo<U(*)[], FElementType(*)[]>)
|
||||||
FORCEINLINE constexpr explicit (Extent != DynamicExtent && N == DynamicExtent) TArrayView(TArrayView<U, N> InValue)
|
FORCEINLINE constexpr explicit (Extent != DynamicExtent && N == DynamicExtent) TArrayView(TArrayView<U, N> InValue)
|
||||||
{
|
{
|
||||||
checkf(Extent == DynamicExtent || Extent == InValue.Num(), TEXT("Illegal view extent. Please check InValue.Num()."));
|
checkf(Extent == DynamicExtent || Extent == InValue.Num(), TEXT("Illegal view extent. Please check InValue.Num()."));
|
||||||
@ -129,7 +129,7 @@ public:
|
|||||||
FORCEINLINE constexpr TArrayView& operator=(const TArrayView&) noexcept = default;
|
FORCEINLINE constexpr TArrayView& operator=(const TArrayView&) noexcept = default;
|
||||||
|
|
||||||
/** Compares the contents of two array views. */
|
/** Compares the contents of two array views. */
|
||||||
NODISCARD friend constexpr bool operator==(TArrayView LHS, TArrayView RHS) requires (CWeaklyEqualityComparable<ElementType>)
|
NODISCARD friend constexpr bool operator==(TArrayView LHS, TArrayView RHS) requires (CWeaklyEqualityComparable<FElementType>)
|
||||||
{
|
{
|
||||||
if (LHS.Num() != RHS.Num()) return false;
|
if (LHS.Num() != RHS.Num()) return false;
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Compares the contents of two array views. */
|
/** Compares the contents of two array views. */
|
||||||
NODISCARD friend constexpr auto operator<=>(TArrayView LHS, TArrayView RHS) requires (CSynthThreeWayComparable<ElementType>)
|
NODISCARD friend constexpr auto operator<=>(TArrayView LHS, TArrayView RHS) requires (CSynthThreeWayComparable<FElementType>)
|
||||||
{
|
{
|
||||||
const size_t NumToCompare = LHS.Num() < RHS.Num() ? LHS.Num() : RHS.Num();
|
const size_t NumToCompare = LHS.Num() < RHS.Num() ? LHS.Num() : RHS.Num();
|
||||||
|
|
||||||
@ -156,36 +156,36 @@ public:
|
|||||||
|
|
||||||
/** Obtains an array view that is a view over the first 'Count' elements of this array view. */
|
/** Obtains an array view that is a view over the first 'Count' elements of this array view. */
|
||||||
template <size_t Count> requires (Extent == DynamicExtent || Extent >= Count)
|
template <size_t Count> requires (Extent == DynamicExtent || Extent >= Count)
|
||||||
NODISCARD FORCEINLINE constexpr TArrayView<ElementType, Count> First() const
|
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, Count> First() const
|
||||||
{
|
{
|
||||||
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
|
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
|
||||||
|
|
||||||
return TArrayView<ElementType, Count>(Begin(), Count);
|
return TArrayView<FElementType, Count>(Begin(), Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Obtains an array view that is a view over the first 'Count' elements of this array view. */
|
/** Obtains an array view that is a view over the first 'Count' elements of this array view. */
|
||||||
NODISCARD FORCEINLINE constexpr TArrayView<ElementType, DynamicExtent> First(size_t Count) const
|
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, DynamicExtent> First(size_t Count) const
|
||||||
{
|
{
|
||||||
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
|
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
|
||||||
|
|
||||||
return TArrayView<ElementType, DynamicExtent>(Begin(), Count);
|
return TArrayView<FElementType, DynamicExtent>(Begin(), Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Obtains an array view that is a view over the last 'Count' elements of this array view. */
|
/** Obtains an array view that is a view over the last 'Count' elements of this array view. */
|
||||||
template <size_t Count> requires (Extent == DynamicExtent || Extent >= Count)
|
template <size_t Count> requires (Extent == DynamicExtent || Extent >= Count)
|
||||||
NODISCARD FORCEINLINE constexpr TArrayView<ElementType, Count> Last() const
|
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, Count> Last() const
|
||||||
{
|
{
|
||||||
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
|
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
|
||||||
|
|
||||||
return TArrayView<ElementType, Count>(End() - Count, Count);
|
return TArrayView<FElementType, Count>(End() - Count, Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Obtains an array view that is a view over the last 'Count' elements of this array view. */
|
/** Obtains an array view that is a view over the last 'Count' elements of this array view. */
|
||||||
NODISCARD FORCEINLINE constexpr TArrayView<ElementType, DynamicExtent> Last(size_t Count) const
|
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, DynamicExtent> Last(size_t Count) const
|
||||||
{
|
{
|
||||||
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
|
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
|
||||||
|
|
||||||
return TArrayView<ElementType, DynamicExtent>(End() - Count, Count);
|
return TArrayView<FElementType, DynamicExtent>(End() - Count, Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Obtains an array view that is a view over the 'Count' elements of this array view starting at 'Offset'. */
|
/** Obtains an array view that is a view over the 'Count' elements of this array view starting at 'Offset'. */
|
||||||
@ -198,11 +198,11 @@ public:
|
|||||||
|
|
||||||
if constexpr (Count != DynamicExtent)
|
if constexpr (Count != DynamicExtent)
|
||||||
{
|
{
|
||||||
return TArrayView<ElementType, SubviewExtent>(Begin() + Offset, Count);
|
return TArrayView<FElementType, SubviewExtent>(Begin() + Offset, Count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return TArrayView<ElementType, SubviewExtent>(Begin() + Offset, Num() - Offset);
|
return TArrayView<FElementType, SubviewExtent>(Begin() + Offset, Num() - Offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,20 +213,20 @@ public:
|
|||||||
|
|
||||||
if (Count != DynamicExtent)
|
if (Count != DynamicExtent)
|
||||||
{
|
{
|
||||||
return TArrayView<ElementType, DynamicExtent>(Begin() + Offset, Count);
|
return TArrayView<FElementType, DynamicExtent>(Begin() + Offset, Count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return TArrayView<ElementType, DynamicExtent>(Begin() + Offset, Num() - Offset);
|
return TArrayView<FElementType, DynamicExtent>(Begin() + Offset, Num() - Offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Obtains an array view to the object representation of the elements of the array view. */
|
/** Obtains an array view to the object representation of the elements of the array view. */
|
||||||
NODISCARD FORCEINLINE constexpr auto AsBytes()
|
NODISCARD FORCEINLINE constexpr auto AsBytes()
|
||||||
{
|
{
|
||||||
constexpr size_t BytesExtent = Extent != DynamicExtent ? sizeof(ElementType) * Extent : DynamicExtent;
|
constexpr size_t BytesExtent = Extent != DynamicExtent ? sizeof(FElementType) * Extent : DynamicExtent;
|
||||||
|
|
||||||
if constexpr (!CConst<ElementType>)
|
if constexpr (!CConst<FElementType>)
|
||||||
{
|
{
|
||||||
return TArrayView<uint8, BytesExtent>(reinterpret_cast<uint8*>(GetData()), NumBytes());
|
return TArrayView<uint8, BytesExtent>(reinterpret_cast<uint8*>(GetData()), NumBytes());
|
||||||
}
|
}
|
||||||
@ -239,47 +239,47 @@ public:
|
|||||||
/** Obtains an array view to the object representation of the elements of the array view. */
|
/** Obtains an array view to the object representation of the elements of the array view. */
|
||||||
NODISCARD FORCEINLINE constexpr auto AsBytes() const
|
NODISCARD FORCEINLINE constexpr auto AsBytes() const
|
||||||
{
|
{
|
||||||
constexpr size_t BytesExtent = Extent != DynamicExtent ? sizeof(ElementType) * Extent : DynamicExtent;
|
constexpr size_t BytesExtent = Extent != DynamicExtent ? sizeof(FElementType) * Extent : DynamicExtent;
|
||||||
|
|
||||||
return TArrayView<const uint8, BytesExtent>(reinterpret_cast<const uint8*>(GetData()), NumBytes());
|
return TArrayView<const uint8, BytesExtent>(reinterpret_cast<const uint8*>(GetData()), NumBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The pointer to the underlying element storage. */
|
/** @return The pointer to the underlying element storage. */
|
||||||
NODISCARD FORCEINLINE constexpr ElementType* GetData() const { return Impl.Pointer; }
|
NODISCARD FORCEINLINE constexpr FElementType* GetData() const { return Impl.Pointer; }
|
||||||
|
|
||||||
/** @return The iterator to the first or end element. */
|
/** @return The iterator to the first or end element. */
|
||||||
NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(this, Impl.Pointer); }
|
NODISCARD FORCEINLINE constexpr FIterator Begin() const { return FIterator(this, Impl.Pointer); }
|
||||||
NODISCARD FORCEINLINE constexpr Iterator End() const { return Iterator(this, Impl.Pointer + Num()); }
|
NODISCARD FORCEINLINE constexpr FIterator End() const { return FIterator(this, Impl.Pointer + Num()); }
|
||||||
|
|
||||||
/** @return The reverse iterator to the first or end element. */
|
/** @return The reverse iterator to the first or end element. */
|
||||||
NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() const { return ReverseIterator(End()); }
|
NODISCARD FORCEINLINE constexpr FReverseIterator RBegin() const { return FReverseIterator(End()); }
|
||||||
NODISCARD FORCEINLINE constexpr ReverseIterator REnd() const { return ReverseIterator(Begin()); }
|
NODISCARD FORCEINLINE constexpr FReverseIterator REnd() const { return FReverseIterator(Begin()); }
|
||||||
|
|
||||||
/** @return The number of elements in the container. */
|
/** @return The number of elements in the container. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t Num() const { if constexpr (Extent == DynamicExtent) { return Impl.ArrayNum; } return Extent; }
|
NODISCARD FORCEINLINE constexpr size_t Num() const { if constexpr (Extent == DynamicExtent) { return Impl.ArrayNum; } return Extent; }
|
||||||
|
|
||||||
/** @return The number of bytes in the container. */
|
/** @return The number of bytes in the container. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t NumBytes() const { return Num() * sizeof(ElementType); }
|
NODISCARD FORCEINLINE constexpr size_t NumBytes() const { return Num() * sizeof(FElementType); }
|
||||||
|
|
||||||
/** @return true if the container is empty, false otherwise. */
|
/** @return true if the container is empty, false otherwise. */
|
||||||
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; }
|
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; }
|
||||||
|
|
||||||
/** @return true if the iterator is valid, false otherwise. */
|
/** @return true if the iterator is valid, false otherwise. */
|
||||||
NODISCARD FORCEINLINE constexpr bool IsValidIterator(Iterator Iter) const { return Begin() <= Iter && Iter <= End(); }
|
NODISCARD FORCEINLINE constexpr bool IsValidIterator(FIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
|
||||||
|
|
||||||
/** @return The reference to the requested element. */
|
/** @return The reference to the requested element. */
|
||||||
NODISCARD FORCEINLINE constexpr Reference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
|
NODISCARD FORCEINLINE constexpr FReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return Impl.Pointer[Index]; }
|
||||||
|
|
||||||
/** @return The reference to the first or last element. */
|
/** @return The reference to the first or last element. */
|
||||||
NODISCARD FORCEINLINE constexpr Reference Front() const { return *Begin(); }
|
NODISCARD FORCEINLINE constexpr FReference Front() const { return *Begin(); }
|
||||||
NODISCARD FORCEINLINE constexpr Reference Back() const { return *(End() - 1); }
|
NODISCARD FORCEINLINE constexpr FReference Back() const { return *(End() - 1); }
|
||||||
|
|
||||||
/** Overloads the GetTypeHash algorithm for TArrayView. */
|
/** Overloads the GetTypeHash algorithm for TArrayView. */
|
||||||
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(TArrayView A) requires (CHashable<ElementType>)
|
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(TArrayView A) requires (CHashable<FElementType>)
|
||||||
{
|
{
|
||||||
size_t Result = 0;
|
size_t Result = 0;
|
||||||
|
|
||||||
for (Iterator Iter = A.Begin(); Iter != A.End(); ++Iter)
|
for (FIterator Iter = A.Begin(); Iter != A.End(); ++Iter)
|
||||||
{
|
{
|
||||||
Result = HashCombine(Result, GetTypeHash(*Iter));
|
Result = HashCombine(Result, GetTypeHash(*Iter));
|
||||||
}
|
}
|
||||||
@ -291,7 +291,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct FImplWithoutNum { ElementType* Pointer; };
|
struct FImplWithoutNum { FElementType* Pointer; };
|
||||||
|
|
||||||
struct FImplWithNum : FImplWithoutNum { size_t ArrayNum; };
|
struct FImplWithNum : FImplWithoutNum { size_t ArrayNum; };
|
||||||
|
|
||||||
@ -299,42 +299,42 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class Iterator final
|
class FIterator final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TRemoveCV<T>;
|
using FElementType = TRemoveCV<T>;
|
||||||
|
|
||||||
FORCEINLINE constexpr Iterator() = default;
|
FORCEINLINE constexpr FIterator() = default;
|
||||||
FORCEINLINE constexpr Iterator(const Iterator&) = default;
|
FORCEINLINE constexpr FIterator(const FIterator&) = default;
|
||||||
FORCEINLINE constexpr Iterator(Iterator&&) = default;
|
FORCEINLINE constexpr FIterator(FIterator&&) = default;
|
||||||
FORCEINLINE constexpr Iterator& operator=(const Iterator&) = default;
|
FORCEINLINE constexpr FIterator& operator=(const FIterator&) = default;
|
||||||
FORCEINLINE constexpr Iterator& operator=(Iterator&&) = default;
|
FORCEINLINE constexpr FIterator& operator=(FIterator&&) = default;
|
||||||
|
|
||||||
NODISCARD friend FORCEINLINE constexpr bool operator==(const Iterator& LHS, const Iterator& RHS) { return LHS.Pointer == RHS.Pointer; }
|
NODISCARD friend FORCEINLINE constexpr bool operator==(const FIterator& LHS, const FIterator& RHS) { return LHS.Pointer == RHS.Pointer; }
|
||||||
|
|
||||||
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const Iterator& LHS, const Iterator& RHS) { return LHS.Pointer <=> RHS.Pointer; }
|
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const FIterator& LHS, const FIterator& RHS) { return LHS.Pointer <=> RHS.Pointer; }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr T& operator*() const { CheckThis(true ); return *Pointer; }
|
NODISCARD FORCEINLINE constexpr T& operator*() const { CheckThis(true ); return *Pointer; }
|
||||||
NODISCARD FORCEINLINE constexpr T* operator->() const { CheckThis(false); return Pointer; }
|
NODISCARD FORCEINLINE constexpr T* operator->() const { CheckThis(false); return Pointer; }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr T& operator[](ptrdiff Index) const { Iterator Temp = *this + Index; return *Temp; }
|
NODISCARD FORCEINLINE constexpr T& operator[](ptrdiff Index) const { FIterator Temp = *this + Index; return *Temp; }
|
||||||
|
|
||||||
FORCEINLINE constexpr Iterator& operator++() { ++Pointer; CheckThis(); return *this; }
|
FORCEINLINE constexpr FIterator& operator++() { ++Pointer; CheckThis(); return *this; }
|
||||||
FORCEINLINE constexpr Iterator& operator--() { --Pointer; CheckThis(); return *this; }
|
FORCEINLINE constexpr FIterator& operator--() { --Pointer; CheckThis(); return *this; }
|
||||||
|
|
||||||
FORCEINLINE constexpr Iterator operator++(int) { Iterator Temp = *this; ++*this; return Temp; }
|
FORCEINLINE constexpr FIterator operator++(int) { FIterator Temp = *this; ++*this; return Temp; }
|
||||||
FORCEINLINE constexpr Iterator operator--(int) { Iterator Temp = *this; --*this; return Temp; }
|
FORCEINLINE constexpr FIterator operator--(int) { FIterator Temp = *this; --*this; return Temp; }
|
||||||
|
|
||||||
FORCEINLINE constexpr Iterator& operator+=(ptrdiff Offset) { Pointer += Offset; CheckThis(); return *this; }
|
FORCEINLINE constexpr FIterator& operator+=(ptrdiff Offset) { Pointer += Offset; CheckThis(); return *this; }
|
||||||
FORCEINLINE constexpr Iterator& operator-=(ptrdiff Offset) { Pointer -= Offset; CheckThis(); return *this; }
|
FORCEINLINE constexpr FIterator& operator-=(ptrdiff Offset) { Pointer -= Offset; CheckThis(); return *this; }
|
||||||
|
|
||||||
NODISCARD friend FORCEINLINE constexpr Iterator operator+(Iterator Iter, ptrdiff Offset) { Iterator Temp = Iter; Temp += Offset; return Temp; }
|
NODISCARD friend FORCEINLINE constexpr FIterator operator+(FIterator Iter, ptrdiff Offset) { FIterator Temp = Iter; Temp += Offset; return Temp; }
|
||||||
NODISCARD friend FORCEINLINE constexpr Iterator operator+(ptrdiff Offset, Iterator Iter) { Iterator Temp = Iter; Temp += Offset; return Temp; }
|
NODISCARD friend FORCEINLINE constexpr FIterator operator+(ptrdiff Offset, FIterator Iter) { FIterator Temp = Iter; Temp += Offset; return Temp; }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr Iterator operator-(ptrdiff Offset) const { Iterator Temp = *this; Temp -= Offset; return Temp; }
|
NODISCARD FORCEINLINE constexpr FIterator operator-(ptrdiff Offset) const { FIterator Temp = *this; Temp -= Offset; return Temp; }
|
||||||
|
|
||||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const Iterator& LHS, const Iterator& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Pointer - RHS.Pointer; }
|
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIterator& LHS, const FIterator& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Pointer - RHS.Pointer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -345,11 +345,11 @@ public:
|
|||||||
T* Pointer = nullptr;
|
T* Pointer = nullptr;
|
||||||
|
|
||||||
# if DO_CHECK
|
# if DO_CHECK
|
||||||
FORCEINLINE constexpr Iterator(const TArrayView* InContainer, T* InPointer)
|
FORCEINLINE constexpr FIterator(const TArrayView* InContainer, T* InPointer)
|
||||||
: Owner(InContainer), Pointer(InPointer)
|
: Owner(InContainer), Pointer(InPointer)
|
||||||
{ }
|
{ }
|
||||||
# else
|
# else
|
||||||
FORCEINLINE constexpr Iterator(const TArrayView* InContainer, T* InPointer)
|
FORCEINLINE constexpr FIterator(const TArrayView* InContainer, T* InPointer)
|
||||||
: Pointer(InPointer)
|
: Pointer(InPointer)
|
||||||
{ }
|
{ }
|
||||||
# endif
|
# endif
|
||||||
|
@ -30,23 +30,23 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using BlockType = InBlockType;
|
using FBlockType = InBlockType;
|
||||||
using ElementType = bool;
|
using FElementType = bool;
|
||||||
using AllocatorType = Allocator;
|
using FAllocatorType = Allocator;
|
||||||
|
|
||||||
class Reference;
|
class FReference;
|
||||||
using ConstReference = bool;
|
using FConstReference = bool;
|
||||||
|
|
||||||
using Iterator = TIteratorImpl<false>;
|
using FIterator = TIteratorImpl<false>;
|
||||||
using ConstIterator = TIteratorImpl<true >;
|
using FConstIterator = TIteratorImpl<true >;
|
||||||
|
|
||||||
using ReverseIterator = TReverseIterator< Iterator>;
|
using FReverseIterator = TReverseIterator< FIterator>;
|
||||||
using ConstReverseIterator = TReverseIterator<ConstIterator>;
|
using FConstReverseIterator = TReverseIterator<FConstIterator>;
|
||||||
|
|
||||||
static_assert(CRandomAccessIterator< Iterator>);
|
static_assert(CRandomAccessIterator< FIterator>);
|
||||||
static_assert(CRandomAccessIterator<ConstIterator>);
|
static_assert(CRandomAccessIterator<FConstIterator>);
|
||||||
|
|
||||||
static constexpr size_t BlockWidth = sizeof(BlockType) * 8;
|
static constexpr size_t BlockWidth = sizeof(FBlockType) * 8;
|
||||||
|
|
||||||
/** Default constructor. Constructs an empty bitset. */
|
/** Default constructor. Constructs an empty bitset. */
|
||||||
FORCEINLINE TBitset() : TBitset(0) { }
|
FORCEINLINE TBitset() : TBitset(0) { }
|
||||||
@ -62,40 +62,40 @@ public:
|
|||||||
/** Constructs a bitset from an integer. */
|
/** Constructs a bitset from an integer. */
|
||||||
TBitset(size_t InCount, uint64 InValue) : TBitset(InCount > 64 ? InCount : 64)
|
TBitset(size_t InCount, uint64 InValue) : TBitset(InCount > 64 ? InCount : 64)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
|
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
|
||||||
|
|
||||||
if constexpr (sizeof(BlockType) == sizeof(uint8))
|
if constexpr (sizeof(FBlockType) == sizeof(uint8))
|
||||||
{
|
{
|
||||||
Impl.Pointer[0] = static_cast<BlockType>(InValue >> 0);
|
Impl.Pointer[0] = static_cast<FBlockType>(InValue >> 0);
|
||||||
Impl.Pointer[1] = static_cast<BlockType>(InValue >> 8);
|
Impl.Pointer[1] = static_cast<FBlockType>(InValue >> 8);
|
||||||
Impl.Pointer[2] = static_cast<BlockType>(InValue >> 16);
|
Impl.Pointer[2] = static_cast<FBlockType>(InValue >> 16);
|
||||||
Impl.Pointer[3] = static_cast<BlockType>(InValue >> 24);
|
Impl.Pointer[3] = static_cast<FBlockType>(InValue >> 24);
|
||||||
Impl.Pointer[4] = static_cast<BlockType>(InValue >> 32);
|
Impl.Pointer[4] = static_cast<FBlockType>(InValue >> 32);
|
||||||
Impl.Pointer[5] = static_cast<BlockType>(InValue >> 40);
|
Impl.Pointer[5] = static_cast<FBlockType>(InValue >> 40);
|
||||||
Impl.Pointer[6] = static_cast<BlockType>(InValue >> 48);
|
Impl.Pointer[6] = static_cast<FBlockType>(InValue >> 48);
|
||||||
Impl.Pointer[7] = static_cast<BlockType>(InValue >> 56);
|
Impl.Pointer[7] = static_cast<FBlockType>(InValue >> 56);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint16))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
|
||||||
{
|
{
|
||||||
Impl.Pointer[0] = static_cast<BlockType>(InValue >> 0);
|
Impl.Pointer[0] = static_cast<FBlockType>(InValue >> 0);
|
||||||
Impl.Pointer[1] = static_cast<BlockType>(InValue >> 16);
|
Impl.Pointer[1] = static_cast<FBlockType>(InValue >> 16);
|
||||||
Impl.Pointer[2] = static_cast<BlockType>(InValue >> 32);
|
Impl.Pointer[2] = static_cast<FBlockType>(InValue >> 32);
|
||||||
Impl.Pointer[3] = static_cast<BlockType>(InValue >> 48);
|
Impl.Pointer[3] = static_cast<FBlockType>(InValue >> 48);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint32))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
|
||||||
{
|
{
|
||||||
Impl.Pointer[0] = static_cast<BlockType>(InValue >> 0);
|
Impl.Pointer[0] = static_cast<FBlockType>(InValue >> 0);
|
||||||
Impl.Pointer[1] = static_cast<BlockType>(InValue >> 32);
|
Impl.Pointer[1] = static_cast<FBlockType>(InValue >> 32);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint64))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
|
||||||
{
|
{
|
||||||
Impl.Pointer[0] = static_cast<BlockType>(InValue >> 0);
|
Impl.Pointer[0] = static_cast<FBlockType>(InValue >> 0);
|
||||||
}
|
}
|
||||||
else check_no_entry();
|
else check_no_entry();
|
||||||
|
|
||||||
size_t BlockInteger = sizeof(uint64) / sizeof(BlockType);
|
size_t BlockInteger = sizeof(uint64) / sizeof(FBlockType);
|
||||||
|
|
||||||
Memory::Memset(Impl.Pointer + BlockInteger, 0, (NumBlocks() - BlockInteger) * sizeof(BlockType));
|
Memory::Memset(Impl.Pointer + BlockInteger, 0, (NumBlocks() - BlockInteger) * sizeof(FBlockType));
|
||||||
|
|
||||||
Impl.BitsetNum = InCount;
|
Impl.BitsetNum = InCount;
|
||||||
}
|
}
|
||||||
@ -112,9 +112,7 @@ public:
|
|||||||
|
|
||||||
new (this) TBitset(InCount);
|
new (this) TBitset(InCount);
|
||||||
|
|
||||||
BlockType* CurrentBlock = Impl.Pointer - 1;
|
for (FReference Ref: *this) Ref = *First++;
|
||||||
|
|
||||||
for (Reference Ref: *this) Ref = *First++;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -135,7 +133,7 @@ public:
|
|||||||
Impl.BlocksMax = Impl->CalculateSlackReserve(NumBlocks());
|
Impl.BlocksMax = Impl->CalculateSlackReserve(NumBlocks());
|
||||||
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
||||||
|
|
||||||
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(BlockType));
|
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(FBlockType));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Move constructor. After the move, 'InValue' is guaranteed to be empty. */
|
/** Move constructor. After the move, 'InValue' is guaranteed to be empty. */
|
||||||
@ -157,7 +155,7 @@ public:
|
|||||||
Impl.BlocksMax = Impl->CalculateSlackReserve(NumBlocks());
|
Impl.BlocksMax = Impl->CalculateSlackReserve(NumBlocks());
|
||||||
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
||||||
|
|
||||||
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(BlockType));
|
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(FBlockType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +186,7 @@ public:
|
|||||||
Impl.BlocksMax = NumToAllocate;
|
Impl.BlocksMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
||||||
|
|
||||||
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(BlockType));
|
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(FBlockType));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -197,7 +195,7 @@ public:
|
|||||||
|
|
||||||
Impl.BitsetNum = InValue.Num();
|
Impl.BitsetNum = InValue.Num();
|
||||||
|
|
||||||
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(BlockType));
|
Memory::Memcpy(Impl.Pointer, InValue.Impl.Pointer, NumBlocks() * sizeof(FBlockType));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -247,14 +245,14 @@ public:
|
|||||||
Impl.BlocksMax = NumToAllocate;
|
Impl.BlocksMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
||||||
|
|
||||||
for (Reference Ref : *this) Ref = *First++;
|
for (FReference Ref : *this) Ref = *First++;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Impl.BitsetNum = GetNum(IL);
|
Impl.BitsetNum = GetNum(IL);
|
||||||
|
|
||||||
for (Reference Ref : *this) Ref = *First++;
|
for (FReference Ref : *this) Ref = *First++;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -271,7 +269,7 @@ public:
|
|||||||
if (LHS.Impl.Pointer[Index] != RHS.Impl.Pointer[Index]) return false;
|
if (LHS.Impl.Pointer[Index] != RHS.Impl.Pointer[Index]) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = LHS.Num() % BlockWidth != 0 ? (1ull << LHS.Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = LHS.Num() % BlockWidth != 0 ? (1ull << LHS.Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
return (LHS.Impl.Pointer[LHS.NumBlocks() - 1] & LastBlockBitmask) == (RHS.Impl.Pointer[LHS.NumBlocks() - 1] & LastBlockBitmask);
|
return (LHS.Impl.Pointer[LHS.NumBlocks() - 1] & LastBlockBitmask) == (RHS.Impl.Pointer[LHS.NumBlocks() - 1] & LastBlockBitmask);
|
||||||
}
|
}
|
||||||
@ -301,7 +299,7 @@ public:
|
|||||||
Impl.Pointer[Index] &= InValue.Impl.Pointer[Index];
|
Impl.Pointer[Index] &= InValue.Impl.Pointer[Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
Impl.Pointer[LastBlock] &= InValue.Impl.Pointer[LastBlock] & LastBlockBitmask;
|
Impl.Pointer[LastBlock] &= InValue.Impl.Pointer[LastBlock] & LastBlockBitmask;
|
||||||
|
|
||||||
@ -339,7 +337,7 @@ public:
|
|||||||
Impl.Pointer[Index] |= InValue.Impl.Pointer[Index];
|
Impl.Pointer[Index] |= InValue.Impl.Pointer[Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
Impl.Pointer[LastBlock] |= InValue.Impl.Pointer[LastBlock] & LastBlockBitmask;
|
Impl.Pointer[LastBlock] |= InValue.Impl.Pointer[LastBlock] & LastBlockBitmask;
|
||||||
}
|
}
|
||||||
@ -372,7 +370,7 @@ public:
|
|||||||
Impl.Pointer[Index] ^= InValue.Impl.Pointer[Index];
|
Impl.Pointer[Index] ^= InValue.Impl.Pointer[Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = InValue.Num() % BlockWidth != 0 ? (1ull << InValue.Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
Impl.Pointer[LastBlock] ^= InValue.Impl.Pointer[LastBlock] & LastBlockBitmask;
|
Impl.Pointer[LastBlock] ^= InValue.Impl.Pointer[LastBlock] & LastBlockBitmask;
|
||||||
}
|
}
|
||||||
@ -473,7 +471,7 @@ public:
|
|||||||
if (Impl.Pointer[Index] != -1) return false;
|
if (Impl.Pointer[Index] != -1) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
return (Impl.Pointer[NumBlocks() - 1] | ~LastBlockBitmask) == -1;
|
return (Impl.Pointer[NumBlocks() - 1] | ~LastBlockBitmask) == -1;
|
||||||
}
|
}
|
||||||
@ -488,7 +486,7 @@ public:
|
|||||||
if (Impl.Pointer[Index] != 0) return true;
|
if (Impl.Pointer[Index] != 0) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
return (Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask) != 0;
|
return (Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask) != 0;
|
||||||
}
|
}
|
||||||
@ -503,24 +501,24 @@ public:
|
|||||||
|
|
||||||
size_t Result = 0;
|
size_t Result = 0;
|
||||||
|
|
||||||
constexpr auto BlockCount = [](BlockType Block)
|
constexpr auto BlockCount = [](FBlockType Block)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
|
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
|
||||||
|
|
||||||
if constexpr (sizeof(BlockType) == sizeof(uint8))
|
if constexpr (sizeof(FBlockType) == sizeof(uint8))
|
||||||
{
|
{
|
||||||
Block = (Block & 0x55ull) + ((Block >> 1) & 0x55ull);
|
Block = (Block & 0x55ull) + ((Block >> 1) & 0x55ull);
|
||||||
Block = (Block & 0x33ull) + ((Block >> 2) & 0x33ull);
|
Block = (Block & 0x33ull) + ((Block >> 2) & 0x33ull);
|
||||||
Block = (Block & 0x0Full) + ((Block >> 4) & 0x0Full);
|
Block = (Block & 0x0Full) + ((Block >> 4) & 0x0Full);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint16))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
|
||||||
{
|
{
|
||||||
Block = (Block & 0x5555ull) + ((Block >> 1) & 0x5555ull);
|
Block = (Block & 0x5555ull) + ((Block >> 1) & 0x5555ull);
|
||||||
Block = (Block & 0x3333ull) + ((Block >> 2) & 0x3333ull);
|
Block = (Block & 0x3333ull) + ((Block >> 2) & 0x3333ull);
|
||||||
Block = (Block & 0x0F0Full) + ((Block >> 4) & 0x0F0Full);
|
Block = (Block & 0x0F0Full) + ((Block >> 4) & 0x0F0Full);
|
||||||
Block = (Block & 0x00FFull) + ((Block >> 8) & 0x00FFull);
|
Block = (Block & 0x00FFull) + ((Block >> 8) & 0x00FFull);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint32))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
|
||||||
{
|
{
|
||||||
Block = (Block & 0x55555555ull) + ((Block >> 1) & 0x55555555ull);
|
Block = (Block & 0x55555555ull) + ((Block >> 1) & 0x55555555ull);
|
||||||
Block = (Block & 0x33333333ull) + ((Block >> 2) & 0x33333333ull);
|
Block = (Block & 0x33333333ull) + ((Block >> 2) & 0x33333333ull);
|
||||||
@ -528,7 +526,7 @@ public:
|
|||||||
Block = (Block & 0x00FF00FFull) + ((Block >> 8) & 0x00FF00FFull);
|
Block = (Block & 0x00FF00FFull) + ((Block >> 8) & 0x00FF00FFull);
|
||||||
Block = (Block & 0x0000FFFFull) + ((Block >> 16) & 0x0000FFFFull);
|
Block = (Block & 0x0000FFFFull) + ((Block >> 16) & 0x0000FFFFull);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint64))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
|
||||||
{
|
{
|
||||||
Block = (Block & 0x5555555555555555ull) + ((Block >> 1) & 0x5555555555555555ull);
|
Block = (Block & 0x5555555555555555ull) + ((Block >> 1) & 0x5555555555555555ull);
|
||||||
Block = (Block & 0x3333333333333333ull) + ((Block >> 2) & 0x3333333333333333ull);
|
Block = (Block & 0x3333333333333333ull) + ((Block >> 2) & 0x3333333333333333ull);
|
||||||
@ -547,7 +545,7 @@ public:
|
|||||||
Result += BlockCount(Impl.Pointer[Index]);
|
Result += BlockCount(Impl.Pointer[Index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
Result += BlockCount(Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask);
|
Result += BlockCount(Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask);
|
||||||
|
|
||||||
@ -557,7 +555,7 @@ public:
|
|||||||
/** Sets all bits to true. */
|
/** Sets all bits to true. */
|
||||||
TBitset& Set(bool InValue = true)
|
TBitset& Set(bool InValue = true)
|
||||||
{
|
{
|
||||||
Memory::Memset(Impl.Pointer, static_cast<uint8>(InValue ? -1 : 0), NumBlocks() * sizeof(BlockType));
|
Memory::Memset(Impl.Pointer, static_cast<uint8>(InValue ? -1 : 0), NumBlocks() * sizeof(FBlockType));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -591,17 +589,17 @@ public:
|
|||||||
checkf(Impl.Pointer[Index] != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
|
checkf(Impl.Pointer[Index] != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
||||||
const BlockType LastBlock = Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask;
|
const FBlockType LastBlock = Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask;
|
||||||
|
|
||||||
checkf(LastBlock != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
|
checkf(LastBlock != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 Result = 0;
|
uint64 Result = 0;
|
||||||
|
|
||||||
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
|
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TBitset is unexpected");
|
||||||
|
|
||||||
if constexpr (sizeof(BlockType) == sizeof(uint8))
|
if constexpr (sizeof(FBlockType) == sizeof(uint8))
|
||||||
{
|
{
|
||||||
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
|
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
|
||||||
Result |= static_cast<uint64>(Impl.Pointer[1]) << 8;
|
Result |= static_cast<uint64>(Impl.Pointer[1]) << 8;
|
||||||
@ -612,19 +610,19 @@ public:
|
|||||||
Result |= static_cast<uint64>(Impl.Pointer[6]) << 48;
|
Result |= static_cast<uint64>(Impl.Pointer[6]) << 48;
|
||||||
Result |= static_cast<uint64>(Impl.Pointer[7]) << 56;
|
Result |= static_cast<uint64>(Impl.Pointer[7]) << 56;
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint16))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
|
||||||
{
|
{
|
||||||
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
|
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
|
||||||
Result |= static_cast<uint64>(Impl.Pointer[1]) << 16;
|
Result |= static_cast<uint64>(Impl.Pointer[1]) << 16;
|
||||||
Result |= static_cast<uint64>(Impl.Pointer[2]) << 32;
|
Result |= static_cast<uint64>(Impl.Pointer[2]) << 32;
|
||||||
Result |= static_cast<uint64>(Impl.Pointer[3]) << 48;
|
Result |= static_cast<uint64>(Impl.Pointer[3]) << 48;
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint32))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
|
||||||
{
|
{
|
||||||
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
|
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
|
||||||
Result |= static_cast<uint64>(Impl.Pointer[1]) << 32;
|
Result |= static_cast<uint64>(Impl.Pointer[1]) << 32;
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint64))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
|
||||||
{
|
{
|
||||||
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
|
Result |= static_cast<uint64>(Impl.Pointer[0]) << 0;
|
||||||
}
|
}
|
||||||
@ -661,7 +659,7 @@ public:
|
|||||||
|
|
||||||
if (NumToAllocate != MaxBlocks())
|
if (NumToAllocate != MaxBlocks())
|
||||||
{
|
{
|
||||||
BlockType* OldAllocation = Impl.Pointer;
|
FBlockType* OldAllocation = Impl.Pointer;
|
||||||
const size_t NumToDestruct = NumBlocks();
|
const size_t NumToDestruct = NumBlocks();
|
||||||
|
|
||||||
Impl.BitsetNum = InCount;
|
Impl.BitsetNum = InCount;
|
||||||
@ -670,11 +668,11 @@ public:
|
|||||||
|
|
||||||
if (NumToDestruct <= Num())
|
if (NumToDestruct <= Num())
|
||||||
{
|
{
|
||||||
Memory::Memcpy(Impl.Pointer, OldAllocation, NumToDestruct * sizeof(BlockType));
|
Memory::Memcpy(Impl.Pointer, OldAllocation, NumToDestruct * sizeof(FBlockType));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Memcpy(Impl.Pointer, OldAllocation, BlocksCount * sizeof(BlockType));
|
Memory::Memcpy(Impl.Pointer, OldAllocation, BlocksCount * sizeof(FBlockType));
|
||||||
}
|
}
|
||||||
|
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
@ -697,12 +695,12 @@ public:
|
|||||||
NumToAllocate = NumToAllocate > MaxBlocks() ? Impl->CalculateSlackGrow(BlocksCount, MaxBlocks()) : NumToAllocate;
|
NumToAllocate = NumToAllocate > MaxBlocks() ? Impl->CalculateSlackGrow(BlocksCount, MaxBlocks()) : NumToAllocate;
|
||||||
NumToAllocate = NumToAllocate < MaxBlocks() ? (bAllowShrinking ? Impl->CalculateSlackShrink(BlocksCount, MaxBlocks()) : MaxBlocks()) : NumToAllocate;
|
NumToAllocate = NumToAllocate < MaxBlocks() ? (bAllowShrinking ? Impl->CalculateSlackShrink(BlocksCount, MaxBlocks()) : MaxBlocks()) : NumToAllocate;
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
||||||
const BlockType BlocksValueToSet = static_cast<BlockType>(InValue ? -1 : 0);
|
const FBlockType BlocksValueToSet = static_cast<FBlockType>(InValue ? -1 : 0);
|
||||||
|
|
||||||
if (NumToAllocate != MaxBlocks())
|
if (NumToAllocate != MaxBlocks())
|
||||||
{
|
{
|
||||||
BlockType* OldAllocation = Impl.Pointer;
|
FBlockType* OldAllocation = Impl.Pointer;
|
||||||
const size_t NumToDestruct = NumBlocks();
|
const size_t NumToDestruct = NumBlocks();
|
||||||
|
|
||||||
Impl.BitsetNum = InCount;
|
Impl.BitsetNum = InCount;
|
||||||
@ -713,16 +711,16 @@ public:
|
|||||||
{
|
{
|
||||||
if (NumToDestruct != 0)
|
if (NumToDestruct != 0)
|
||||||
{
|
{
|
||||||
Memory::Memcpy(Impl.Pointer, OldAllocation, (NumToDestruct - 1) * sizeof(BlockType));
|
Memory::Memcpy(Impl.Pointer, OldAllocation, (NumToDestruct - 1) * sizeof(FBlockType));
|
||||||
|
|
||||||
Impl.Pointer[NumToDestruct - 1] = OldAllocation[NumToDestruct - 1] & LastBlockBitmask | BlocksValueToSet & ~LastBlockBitmask;
|
Impl.Pointer[NumToDestruct - 1] = OldAllocation[NumToDestruct - 1] & LastBlockBitmask | BlocksValueToSet & ~LastBlockBitmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Memset(Impl.Pointer + NumToDestruct, static_cast<uint8>(BlocksValueToSet), (BlocksCount - NumToDestruct) * sizeof(BlockType));
|
Memory::Memset(Impl.Pointer + NumToDestruct, static_cast<uint8>(BlocksValueToSet), (BlocksCount - NumToDestruct) * sizeof(FBlockType));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Memcpy(Impl.Pointer, OldAllocation, BlocksCount * sizeof(BlockType));
|
Memory::Memcpy(Impl.Pointer, OldAllocation, BlocksCount * sizeof(FBlockType));
|
||||||
}
|
}
|
||||||
|
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
@ -739,7 +737,7 @@ public:
|
|||||||
Impl.Pointer[NumBlocks() - 1] = Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask | BlocksValueToSet & ~LastBlockBitmask;
|
Impl.Pointer[NumBlocks() - 1] = Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask | BlocksValueToSet & ~LastBlockBitmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Memset(Impl.Pointer + NumBlocks(), static_cast<uint8>(BlocksValueToSet), (BlocksCount - NumBlocks()) * sizeof(BlockType));
|
Memory::Memset(Impl.Pointer + NumBlocks(), static_cast<uint8>(BlocksValueToSet), (BlocksCount - NumBlocks()) * sizeof(FBlockType));
|
||||||
}
|
}
|
||||||
|
|
||||||
Impl.BitsetNum = InCount;
|
Impl.BitsetNum = InCount;
|
||||||
@ -753,14 +751,14 @@ public:
|
|||||||
const size_t BlocksCount = (InCount + BlockWidth - 1) / BlockWidth;
|
const size_t BlocksCount = (InCount + BlockWidth - 1) / BlockWidth;
|
||||||
|
|
||||||
const size_t NumToAllocate = Impl->CalculateSlackReserve(BlocksCount);
|
const size_t NumToAllocate = Impl->CalculateSlackReserve(BlocksCount);
|
||||||
BlockType* OldAllocation = Impl.Pointer;
|
FBlockType* OldAllocation = Impl.Pointer;
|
||||||
|
|
||||||
check(NumToAllocate > MaxBlocks());
|
check(NumToAllocate > MaxBlocks());
|
||||||
|
|
||||||
Impl.BlocksMax = NumToAllocate;
|
Impl.BlocksMax = NumToAllocate;
|
||||||
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
||||||
|
|
||||||
Memory::Memcpy(Impl.Pointer, OldAllocation, NumBlocks() * sizeof(BlockType));
|
Memory::Memcpy(Impl.Pointer, OldAllocation, NumBlocks() * sizeof(FBlockType));
|
||||||
|
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
}
|
}
|
||||||
@ -774,31 +772,31 @@ public:
|
|||||||
|
|
||||||
if (NumToAllocate == MaxBlocks()) return;
|
if (NumToAllocate == MaxBlocks()) return;
|
||||||
|
|
||||||
BlockType* OldAllocation = Impl.Pointer;
|
FBlockType* OldAllocation = Impl.Pointer;
|
||||||
|
|
||||||
Impl.BitsetNum = NumToAllocate * BlockWidth;
|
Impl.BitsetNum = NumToAllocate * BlockWidth;
|
||||||
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
Impl.Pointer = Impl->Allocate(MaxBlocks());
|
||||||
|
|
||||||
Memory::Memcpy(Impl.Pointer, OldAllocation, NumBlocks() * sizeof(BlockType));
|
Memory::Memcpy(Impl.Pointer, OldAllocation, NumBlocks() * sizeof(FBlockType));
|
||||||
|
|
||||||
Impl->Deallocate(OldAllocation);
|
Impl->Deallocate(OldAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The pointer to the underlying element storage. */
|
/** @return The pointer to the underlying element storage. */
|
||||||
NODISCARD FORCEINLINE BlockType* GetData() { return Impl.Pointer; }
|
NODISCARD FORCEINLINE FBlockType* GetData() { return Impl.Pointer; }
|
||||||
NODISCARD FORCEINLINE const BlockType* GetData() const { return Impl.Pointer; }
|
NODISCARD FORCEINLINE const FBlockType* GetData() const { return Impl.Pointer; }
|
||||||
|
|
||||||
/** @return The iterator to the first or end bit. */
|
/** @return The iterator to the first or end bit. */
|
||||||
NODISCARD FORCEINLINE Iterator Begin() { return Iterator(this, Impl.Pointer, 0); }
|
NODISCARD FORCEINLINE FIterator Begin() { return FIterator(this, Impl.Pointer, 0); }
|
||||||
NODISCARD FORCEINLINE ConstIterator Begin() const { return ConstIterator(this, Impl.Pointer, 0); }
|
NODISCARD FORCEINLINE FConstIterator Begin() const { return FConstIterator(this, Impl.Pointer, 0); }
|
||||||
NODISCARD FORCEINLINE Iterator End() { return Iterator(this, Impl.Pointer, Num()); }
|
NODISCARD FORCEINLINE FIterator End() { return FIterator(this, Impl.Pointer, Num()); }
|
||||||
NODISCARD FORCEINLINE ConstIterator End() const { return ConstIterator(this, Impl.Pointer, Num()); }
|
NODISCARD FORCEINLINE FConstIterator End() const { return FConstIterator(this, Impl.Pointer, Num()); }
|
||||||
|
|
||||||
/** @return The reverse iterator to the first or end bit. */
|
/** @return The reverse iterator to the first or end bit. */
|
||||||
NODISCARD FORCEINLINE ReverseIterator RBegin() { return ReverseIterator(End()); }
|
NODISCARD FORCEINLINE FReverseIterator RBegin() { return FReverseIterator(End()); }
|
||||||
NODISCARD FORCEINLINE ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
|
NODISCARD FORCEINLINE FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
|
||||||
NODISCARD FORCEINLINE ReverseIterator REnd() { return ReverseIterator(Begin()); }
|
NODISCARD FORCEINLINE FReverseIterator REnd() { return FReverseIterator(Begin()); }
|
||||||
NODISCARD FORCEINLINE ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); }
|
NODISCARD FORCEINLINE FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
|
||||||
|
|
||||||
/** @return The number of bits in the bitset. */
|
/** @return The number of bits in the bitset. */
|
||||||
NODISCARD FORCEINLINE size_t Num() const { return Impl.BitsetNum; }
|
NODISCARD FORCEINLINE size_t Num() const { return Impl.BitsetNum; }
|
||||||
@ -816,17 +814,17 @@ public:
|
|||||||
NODISCARD FORCEINLINE bool IsEmpty() const { return Num() == 0; }
|
NODISCARD FORCEINLINE bool IsEmpty() const { return Num() == 0; }
|
||||||
|
|
||||||
/** @return true if the iterator is valid, false otherwise. */
|
/** @return true if the iterator is valid, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool IsValidIterator(ConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
|
NODISCARD FORCEINLINE bool IsValidIterator(FConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
|
||||||
|
|
||||||
/** @return The reference to the requested bit. */
|
/** @return The reference to the requested bit. */
|
||||||
NODISCARD FORCEINLINE Reference operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
|
NODISCARD FORCEINLINE FReference operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
|
||||||
NODISCARD FORCEINLINE ConstReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
|
NODISCARD FORCEINLINE FConstReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
|
||||||
|
|
||||||
/** @return The reference to the first or last bit. */
|
/** @return The reference to the first or last bit. */
|
||||||
NODISCARD FORCEINLINE Reference Front() { return *Begin(); }
|
NODISCARD FORCEINLINE FReference Front() { return *Begin(); }
|
||||||
NODISCARD FORCEINLINE ConstReference Front() const { return *Begin(); }
|
NODISCARD FORCEINLINE FConstReference Front() const { return *Begin(); }
|
||||||
NODISCARD FORCEINLINE Reference Back() { return *(End() - 1); }
|
NODISCARD FORCEINLINE FReference Back() { return *(End() - 1); }
|
||||||
NODISCARD FORCEINLINE ConstReference Back() const { return *(End() - 1); }
|
NODISCARD FORCEINLINE FConstReference Back() const { return *(End() - 1); }
|
||||||
|
|
||||||
/** Erases all bits from the bitset. After this call, Num() returns zero. */
|
/** Erases all bits from the bitset. After this call, Num() returns zero. */
|
||||||
void Reset(bool bAllowShrinking = true)
|
void Reset(bool bAllowShrinking = true)
|
||||||
@ -859,7 +857,7 @@ public:
|
|||||||
Result = HashCombine(Result, GetTypeHash(A.Impl.Pointer[Index]));
|
Result = HashCombine(Result, GetTypeHash(A.Impl.Pointer[Index]));
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = A.Num() % BlockWidth != 0 ? (1ull << A.Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = A.Num() % BlockWidth != 0 ? (1ull << A.Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
return HashCombine(Result, GetTypeHash(A.Impl.Pointer[A.NumBlocks() - 1] & LastBlockBitmask));
|
return HashCombine(Result, GetTypeHash(A.Impl.Pointer[A.NumBlocks() - 1] & LastBlockBitmask));
|
||||||
}
|
}
|
||||||
@ -889,27 +887,27 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ALLOCATOR_WRAPPER_BEGIN(AllocatorType, BlockType, Impl)
|
ALLOCATOR_WRAPPER_BEGIN(FAllocatorType, FBlockType, Impl)
|
||||||
{
|
{
|
||||||
size_t BitsetNum;
|
size_t BitsetNum;
|
||||||
size_t BlocksMax;
|
size_t BlocksMax;
|
||||||
BlockType* Pointer;
|
FBlockType* Pointer;
|
||||||
}
|
}
|
||||||
ALLOCATOR_WRAPPER_END(AllocatorType, BlockType, Impl)
|
ALLOCATOR_WRAPPER_END(FAllocatorType, FBlockType, Impl)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class Reference final : private FSingleton
|
class FReference final : private FSingleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FORCEINLINE Reference& operator=(bool InValue) { Data = (Data & ~Mask) | (InValue ? Mask : 0); return *this; }
|
FORCEINLINE FReference& operator=(bool InValue) { Data = (Data & ~Mask) | (InValue ? Mask : 0); return *this; }
|
||||||
|
|
||||||
FORCEINLINE Reference& operator=(const Reference& InValue) { *this = static_cast<bool>(InValue); return *this; }
|
FORCEINLINE FReference& operator=(const FReference& InValue) { *this = static_cast<bool>(InValue); return *this; }
|
||||||
|
|
||||||
FORCEINLINE Reference& operator&=(bool InValue) { Data &= InValue ? -1 : ~Mask; return *this; }
|
FORCEINLINE FReference& operator&=(bool InValue) { Data &= InValue ? -1 : ~Mask; return *this; }
|
||||||
FORCEINLINE Reference& operator|=(bool InValue) { Data |= InValue ? Mask : 0; return *this; }
|
FORCEINLINE FReference& operator|=(bool InValue) { Data |= InValue ? Mask : 0; return *this; }
|
||||||
FORCEINLINE Reference& operator^=(bool InValue) { *this = InValue ^ *this; return *this; }
|
FORCEINLINE FReference& operator^=(bool InValue) { *this = InValue ^ *this; return *this; }
|
||||||
|
|
||||||
FORCEINLINE bool operator~() const { return !*this; }
|
FORCEINLINE bool operator~() const { return !*this; }
|
||||||
|
|
||||||
@ -917,14 +915,14 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
FORCEINLINE Reference(BlockType& InData, BlockType InMask)
|
FORCEINLINE FReference(FBlockType& InData, FBlockType InMask)
|
||||||
: Data(InData), Mask(InMask)
|
: Data(InData), Mask(InMask)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
BlockType& Data;
|
FBlockType& Data;
|
||||||
BlockType Mask;
|
FBlockType Mask;
|
||||||
|
|
||||||
friend Iterator;
|
friend FIterator;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -935,7 +933,7 @@ private:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = bool;
|
using FElementType = bool;
|
||||||
|
|
||||||
FORCEINLINE TIteratorImpl() = default;
|
FORCEINLINE TIteratorImpl() = default;
|
||||||
|
|
||||||
@ -958,8 +956,8 @@ private:
|
|||||||
|
|
||||||
NODISCARD friend FORCEINLINE strong_ordering operator<=>(const TIteratorImpl& LHS, const TIteratorImpl& RHS) { check(LHS.Pointer == RHS.Pointer); return LHS.BitOffset <=> RHS.BitOffset; }
|
NODISCARD friend FORCEINLINE strong_ordering operator<=>(const TIteratorImpl& LHS, const TIteratorImpl& RHS) { check(LHS.Pointer == RHS.Pointer); return LHS.BitOffset <=> RHS.BitOffset; }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE Reference operator*() const requires (!bConst) { CheckThis(true); return Reference(*(Pointer + BitOffset / BlockWidth), 1ull << BitOffset % BlockWidth); }
|
NODISCARD FORCEINLINE FReference operator*() const requires (!bConst) { CheckThis(true); return FReference(*(Pointer + BitOffset / BlockWidth), 1ull << BitOffset % BlockWidth); }
|
||||||
NODISCARD FORCEINLINE ConstReference operator*() const requires ( bConst) { CheckThis(true); return (*(Pointer + BitOffset / BlockWidth) & (1ull << BitOffset % BlockWidth)); }
|
NODISCARD FORCEINLINE FConstReference operator*() const requires ( bConst) { CheckThis(true); return (*(Pointer + BitOffset / BlockWidth) & (1ull << BitOffset % BlockWidth)); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE auto operator[](ptrdiff Index) const { TIteratorImpl Temp = *this + Index; return *Temp; }
|
NODISCARD FORCEINLINE auto operator[](ptrdiff Index) const { TIteratorImpl Temp = *this + Index; return *Temp; }
|
||||||
|
|
||||||
@ -985,17 +983,17 @@ private:
|
|||||||
const TBitset* Owner = nullptr;
|
const TBitset* Owner = nullptr;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
using BlockPtr = TConditional<bConst, const BlockType*, BlockType*>;
|
using FBlockPtr = TConditional<bConst, const FBlockType*, FBlockType*>;
|
||||||
|
|
||||||
BlockPtr Pointer = nullptr;
|
FBlockPtr Pointer = nullptr;
|
||||||
size_t BitOffset = 0;
|
size_t BitOffset = 0;
|
||||||
|
|
||||||
# if DO_CHECK
|
# if DO_CHECK
|
||||||
FORCEINLINE TIteratorImpl(const TBitset* InContainer, BlockPtr InPointer, size_t Offset)
|
FORCEINLINE TIteratorImpl(const TBitset* InContainer, FBlockPtr InPointer, size_t Offset)
|
||||||
: Owner(InContainer), Pointer(InPointer), BitOffset(Offset)
|
: Owner(InContainer), Pointer(InPointer), BitOffset(Offset)
|
||||||
{ }
|
{ }
|
||||||
# else
|
# else
|
||||||
FORCEINLINE TIteratorImpl(const TBitset* InContainer, BlockPtr InPointer, size_t Offset)
|
FORCEINLINE TIteratorImpl(const TBitset* InContainer, FBlockPtr InPointer, size_t Offset)
|
||||||
: Pointer(InPointer), BitOffset(Offset)
|
: Pointer(InPointer), BitOffset(Offset)
|
||||||
{ }
|
{ }
|
||||||
# endif
|
# endif
|
||||||
|
@ -28,20 +28,20 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
using AllocatorType = Allocator;
|
using FAllocatorType = Allocator;
|
||||||
|
|
||||||
using Reference = T&;
|
using FReference = T&;
|
||||||
using ConstReference = const T&;
|
using FConstReference = const T&;
|
||||||
|
|
||||||
using Iterator = TIteratorImpl<false>;
|
using FIterator = TIteratorImpl<false>;
|
||||||
using ConstIterator = TIteratorImpl<true >;
|
using FConstIterator = TIteratorImpl<true >;
|
||||||
|
|
||||||
using ReverseIterator = TReverseIterator< Iterator>;
|
using FReverseIterator = TReverseIterator< FIterator>;
|
||||||
using ConstReverseIterator = TReverseIterator<ConstIterator>;
|
using FConstReverseIterator = TReverseIterator<FConstIterator>;
|
||||||
|
|
||||||
static_assert(CBidirectionalIterator< Iterator>);
|
static_assert(CBidirectionalIterator< FIterator>);
|
||||||
static_assert(CBidirectionalIterator<ConstIterator>);
|
static_assert(CBidirectionalIterator<FConstIterator>);
|
||||||
|
|
||||||
/** Default constructor. Constructs an empty container with a default-constructed allocator. */
|
/** Default constructor. Constructs an empty container with a default-constructed allocator. */
|
||||||
TList()
|
TList()
|
||||||
@ -54,7 +54,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs the container with 'Count' default instances of T. */
|
/** Constructs the container with 'Count' default instances of T. */
|
||||||
explicit TList(size_t Count) requires (CDefaultConstructible<ElementType>) : TList()
|
explicit TList(size_t Count) requires (CDefaultConstructible<FElementType>) : TList()
|
||||||
{
|
{
|
||||||
FNode* EndNode = Impl.HeadNode->PrevNode;
|
FNode* EndNode = Impl.HeadNode->PrevNode;
|
||||||
|
|
||||||
@ -75,12 +75,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs the container with 'Count' copies of elements with 'InValue'. */
|
/** Constructs the container with 'Count' copies of elements with 'InValue'. */
|
||||||
TList(size_t Count, const ElementType& InValue) requires (CCopyable<ElementType>)
|
TList(size_t Count, const FElementType& InValue) requires (CCopyable<FElementType>)
|
||||||
: TList(MakeCountedConstantIterator(InValue, Count), DefaultSentinel)
|
: TList(MakeCountedConstantIterator(InValue, Count), DefaultSentinel)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** Constructs the container with the contents of the range ['First', 'Last'). */
|
/** Constructs the container with the contents of the range ['First', 'Last'). */
|
||||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
|
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
|
||||||
TList(I First, S Last) : TList()
|
TList(I First, S Last) : TList()
|
||||||
{
|
{
|
||||||
FNode* EndNode = Impl.HeadNode->PrevNode;
|
FNode* EndNode = Impl.HeadNode->PrevNode;
|
||||||
@ -102,13 +102,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Copy constructor. Constructs the container with the copy of the contents of 'InValue'. */
|
/** Copy constructor. Constructs the container with the copy of the contents of 'InValue'. */
|
||||||
FORCEINLINE TList(const TList& InValue) requires (CCopyConstructible<ElementType>) : TList(InValue.Begin(), InValue.End()) { }
|
FORCEINLINE TList(const TList& InValue) requires (CCopyConstructible<FElementType>) : TList(InValue.Begin(), InValue.End()) { }
|
||||||
|
|
||||||
/** Move constructor. After the move, 'InValue' is guaranteed to be empty. */
|
/** Move constructor. After the move, 'InValue' is guaranteed to be empty. */
|
||||||
FORCEINLINE TList(TList&& InValue) : TList() { Swap(*this, InValue); }
|
FORCEINLINE TList(TList&& InValue) : TList() { Swap(*this, InValue); }
|
||||||
|
|
||||||
/** Constructs the container with the contents of the initializer list. */
|
/** Constructs the container with the contents of the initializer list. */
|
||||||
FORCEINLINE TList(initializer_list<ElementType> IL) requires (CCopyConstructible<ElementType>) : TList(Iteration::Begin(IL), Iteration::End(IL)) { }
|
FORCEINLINE TList(initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) : TList(Iteration::Begin(IL), Iteration::End(IL)) { }
|
||||||
|
|
||||||
/** Destructs the list. The destructors of the elements are called and the used storage is deallocated. */
|
/** Destructs the list. The destructors of the elements are called and the used storage is deallocated. */
|
||||||
~TList()
|
~TList()
|
||||||
@ -129,12 +129,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Copy assignment operator. Replaces the contents with a copy of the contents of 'InValue'. */
|
/** Copy assignment operator. Replaces the contents with a copy of the contents of 'InValue'. */
|
||||||
TList& operator=(const TList& InValue) requires (CCopyable<ElementType>)
|
TList& operator=(const TList& InValue) requires (CCopyable<FElementType>)
|
||||||
{
|
{
|
||||||
if (&InValue == this) UNLIKELY return *this;
|
if (&InValue == this) UNLIKELY return *this;
|
||||||
|
|
||||||
Iterator ThisIter = Begin();
|
FIterator ThisIter = Begin();
|
||||||
ConstIterator OtherIter = InValue.Begin();
|
FConstIterator OtherIter = InValue.Begin();
|
||||||
|
|
||||||
while (ThisIter != End() && OtherIter != InValue.End())
|
while (ThisIter != End() && OtherIter != InValue.End())
|
||||||
{
|
{
|
||||||
@ -166,10 +166,10 @@ public:
|
|||||||
FORCEINLINE TList& operator=(TList&& InValue) { Swap(*this, InValue); InValue.Reset(); return *this; }
|
FORCEINLINE TList& operator=(TList&& InValue) { Swap(*this, InValue); InValue.Reset(); return *this; }
|
||||||
|
|
||||||
/** Replaces the contents with those identified by initializer list. */
|
/** Replaces the contents with those identified by initializer list. */
|
||||||
TList& operator=(initializer_list<ElementType> IL) requires (CCopyable<ElementType>)
|
TList& operator=(initializer_list<FElementType> IL) requires (CCopyable<FElementType>)
|
||||||
{
|
{
|
||||||
Iterator ThisIter = Begin();
|
FIterator ThisIter = Begin();
|
||||||
const ElementType* OtherIter = Iteration::Begin(IL);
|
const FElementType* OtherIter = Iteration::Begin(IL);
|
||||||
|
|
||||||
while (ThisIter != End() && OtherIter != Iteration::End(IL))
|
while (ThisIter != End() && OtherIter != Iteration::End(IL))
|
||||||
{
|
{
|
||||||
@ -198,12 +198,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Compares the contents of two lists. */
|
/** Compares the contents of two lists. */
|
||||||
NODISCARD friend bool operator==(const TList& LHS, const TList& RHS) requires (CWeaklyEqualityComparable<ElementType>)
|
NODISCARD friend bool operator==(const TList& LHS, const TList& RHS) requires (CWeaklyEqualityComparable<FElementType>)
|
||||||
{
|
{
|
||||||
if (LHS.Num() != RHS.Num()) return false;
|
if (LHS.Num() != RHS.Num()) return false;
|
||||||
|
|
||||||
ConstIterator LHSIter = LHS.Begin();
|
FConstIterator LHSIter = LHS.Begin();
|
||||||
ConstIterator RHSIter = RHS.Begin();
|
FConstIterator RHSIter = RHS.Begin();
|
||||||
|
|
||||||
while (LHSIter != LHS.End())
|
while (LHSIter != LHS.End())
|
||||||
{
|
{
|
||||||
@ -219,10 +219,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
||||||
NODISCARD friend auto operator<=>(const TList& LHS, const TList& RHS) requires (CSynthThreeWayComparable<ElementType>)
|
NODISCARD friend auto operator<=>(const TList& LHS, const TList& RHS) requires (CSynthThreeWayComparable<FElementType>)
|
||||||
{
|
{
|
||||||
ConstIterator LHSIter = LHS.Begin();
|
FConstIterator LHSIter = LHS.Begin();
|
||||||
ConstIterator RHSIter = RHS.Begin();
|
FConstIterator RHSIter = RHS.Begin();
|
||||||
|
|
||||||
while (LHSIter != LHS.End() && RHSIter != RHS.End())
|
while (LHSIter != LHS.End() && RHSIter != RHS.End())
|
||||||
{
|
{
|
||||||
@ -236,22 +236,22 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts 'InValue' before 'Iter' in the container. */
|
/** Inserts 'InValue' before 'Iter' in the container. */
|
||||||
FORCEINLINE Iterator Insert(ConstIterator Iter, const ElementType& InValue) requires (CCopyConstructible<ElementType>) { return Emplace(Iter, InValue); }
|
FORCEINLINE FIterator Insert(FConstIterator Iter, const FElementType& InValue) requires (CCopyConstructible<FElementType>) { return Emplace(Iter, InValue); }
|
||||||
|
|
||||||
/** Inserts 'InValue' before 'Iter' in the container. */
|
/** Inserts 'InValue' before 'Iter' in the container. */
|
||||||
FORCEINLINE Iterator Insert(ConstIterator Iter, ElementType&& InValue) requires (CMoveConstructible<ElementType>) { return Emplace(Iter, MoveTemp(InValue)); }
|
FORCEINLINE FIterator Insert(FConstIterator Iter, FElementType&& InValue) requires (CMoveConstructible<FElementType>) { return Emplace(Iter, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Inserts 'Count' copies of the 'InValue' before 'Iter' in the container. */
|
/** Inserts 'Count' copies of the 'InValue' before 'Iter' in the container. */
|
||||||
Iterator Insert(ConstIterator Iter, size_t Count, const ElementType& InValue) requires (CCopyConstructible<ElementType>)
|
FIterator Insert(FConstIterator Iter, size_t Count, const FElementType& InValue) requires (CCopyConstructible<FElementType>)
|
||||||
{
|
{
|
||||||
return Insert(Iter, MakeCountedConstantIterator(InValue, Count), DefaultSentinel);
|
return Insert(Iter, MakeCountedConstantIterator(InValue, Count), DefaultSentinel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts elements from range ['First', 'Last') before 'Iter'. */
|
/** Inserts elements from range ['First', 'Last') before 'Iter'. */
|
||||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
|
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
|
||||||
Iterator Insert(ConstIterator Iter, I First, S Last)
|
FIterator Insert(FConstIterator Iter, I First, S Last)
|
||||||
{
|
{
|
||||||
if (First == Last) return Iterator(Iter.Pointer);
|
if (First == Last) return FIterator(Iter.Pointer);
|
||||||
|
|
||||||
FNode* InsertNode = Iter.Pointer->PrevNode;
|
FNode* InsertNode = Iter.Pointer->PrevNode;
|
||||||
|
|
||||||
@ -279,15 +279,15 @@ public:
|
|||||||
InsertNode->NextNode = Iter.Pointer;
|
InsertNode->NextNode = Iter.Pointer;
|
||||||
Iter.Pointer->PrevNode = InsertNode;
|
Iter.Pointer->PrevNode = InsertNode;
|
||||||
|
|
||||||
return Iterator(FirstNode);
|
return FIterator(FirstNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts elements from initializer list before 'Iter' in the container. */
|
/** Inserts elements from initializer list before 'Iter' in the container. */
|
||||||
FORCEINLINE Iterator Insert(ConstIterator Iter, initializer_list<ElementType> IL) requires (CCopyConstructible<ElementType>) { return Insert(Iter, Iteration::Begin(IL), Iteration::End(IL)); }
|
FORCEINLINE FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) { return Insert(Iter, Iteration::Begin(IL), Iteration::End(IL)); }
|
||||||
|
|
||||||
/** Inserts a new element into the container directly before 'Iter'. */
|
/** Inserts a new element into the container directly before 'Iter'. */
|
||||||
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...>)
|
template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...>)
|
||||||
Iterator Emplace(ConstIterator Iter, Ts&&... Args)
|
FIterator Emplace(FConstIterator Iter, Ts&&... Args)
|
||||||
{
|
{
|
||||||
FNode* Node = new (Impl->Allocate(1)) FNode(InPlace, Forward<Ts>(Args)...);
|
FNode* Node = new (Impl->Allocate(1)) FNode(InPlace, Forward<Ts>(Args)...);
|
||||||
|
|
||||||
@ -299,11 +299,11 @@ public:
|
|||||||
Node->PrevNode->NextNode = Node;
|
Node->PrevNode->NextNode = Node;
|
||||||
Node->NextNode->PrevNode = Node;
|
Node->NextNode->PrevNode = Node;
|
||||||
|
|
||||||
return Iterator(Node);
|
return FIterator(Node);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes the element at 'Iter' in the container. */
|
/** Removes the element at 'Iter' in the container. */
|
||||||
Iterator Erase(ConstIterator Iter)
|
FIterator Erase(FConstIterator Iter)
|
||||||
{
|
{
|
||||||
FNode* NodeToErase = Iter.Pointer;
|
FNode* NodeToErase = Iter.Pointer;
|
||||||
|
|
||||||
@ -319,11 +319,11 @@ public:
|
|||||||
|
|
||||||
--Impl.ListNum;
|
--Impl.ListNum;
|
||||||
|
|
||||||
return Iterator(NextNode);
|
return FIterator(NextNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes the elements in the range ['First', 'Last') in the container. */
|
/** Removes the elements in the range ['First', 'Last') in the container. */
|
||||||
Iterator Erase(ConstIterator First, ConstIterator Last)
|
FIterator Erase(FConstIterator First, FConstIterator Last)
|
||||||
{
|
{
|
||||||
FNode* FirstToErase = First.Pointer;
|
FNode* FirstToErase = First.Pointer;
|
||||||
FNode* LastToErase = Last.Pointer;
|
FNode* LastToErase = Last.Pointer;
|
||||||
@ -343,43 +343,43 @@ public:
|
|||||||
FirstToErase = NextNode;
|
FirstToErase = NextNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Iterator(LastToErase);
|
return FIterator(LastToErase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Appends the given element value to the end of the container. */
|
/** Appends the given element value to the end of the container. */
|
||||||
FORCEINLINE void PushBack(const ElementType& InValue) requires (CCopyConstructible<ElementType>) { EmplaceBack(InValue); }
|
FORCEINLINE void PushBack(const FElementType& InValue) requires (CCopyConstructible<FElementType>) { EmplaceBack(InValue); }
|
||||||
|
|
||||||
/** Appends the given element value to the end of the container. */
|
/** Appends the given element value to the end of the container. */
|
||||||
FORCEINLINE void PushBack(ElementType&& InValue) requires (CMoveConstructible<ElementType>) { EmplaceBack(MoveTemp(InValue)); }
|
FORCEINLINE void PushBack(FElementType&& InValue) requires (CMoveConstructible<FElementType>) { EmplaceBack(MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Appends a new element to the end of the container. */
|
/** Appends a new element to the end of the container. */
|
||||||
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...>)
|
template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...>)
|
||||||
FORCEINLINE Reference EmplaceBack(Ts&&... Args) { return *Emplace(End(), Forward<Ts>(Args)...); }
|
FORCEINLINE FReference EmplaceBack(Ts&&... Args) { return *Emplace(End(), Forward<Ts>(Args)...); }
|
||||||
|
|
||||||
/** Removes the last element of the container. The list cannot be empty. */
|
/** Removes the last element of the container. The list cannot be empty. */
|
||||||
FORCEINLINE void PopBack() { Erase(--End()); }
|
FORCEINLINE void PopBack() { Erase(--End()); }
|
||||||
|
|
||||||
/** Prepends the given element value to the beginning of the container. */
|
/** Prepends the given element value to the beginning of the container. */
|
||||||
FORCEINLINE void PushFront(const ElementType& InValue) requires (CCopyConstructible<ElementType>) { EmplaceFront(InValue); }
|
FORCEINLINE void PushFront(const FElementType& InValue) requires (CCopyConstructible<FElementType>) { EmplaceFront(InValue); }
|
||||||
|
|
||||||
/** Prepends the given element value to the beginning of the container. */
|
/** Prepends the given element value to the beginning of the container. */
|
||||||
FORCEINLINE void PushFront(ElementType&& InValue) requires (CMoveConstructible<ElementType>) { EmplaceFront(MoveTemp(InValue)); }
|
FORCEINLINE void PushFront(FElementType&& InValue) requires (CMoveConstructible<FElementType>) { EmplaceFront(MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Prepends a new element to the beginning of the container. */
|
/** Prepends a new element to the beginning of the container. */
|
||||||
template <typename... Ts> requires (CConstructibleFrom<ElementType, Ts...>)
|
template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...>)
|
||||||
FORCEINLINE Reference EmplaceFront(Ts&&... Args) { return *Emplace(Begin(), Forward<Ts>(Args)...); }
|
FORCEINLINE FReference EmplaceFront(Ts&&... Args) { return *Emplace(Begin(), Forward<Ts>(Args)...); }
|
||||||
|
|
||||||
/** Removes the first element of the container. The list cannot be empty. */
|
/** Removes the first element of the container. The list cannot be empty. */
|
||||||
FORCEINLINE void PopFront() { Erase(Begin()); }
|
FORCEINLINE void PopFront() { Erase(Begin()); }
|
||||||
|
|
||||||
/** Resizes the container to contain 'Count' elements. Additional default elements are appended. */
|
/** Resizes the container to contain 'Count' elements. Additional default elements are appended. */
|
||||||
void SetNum(size_t Count) requires (CDefaultConstructible<ElementType>)
|
void SetNum(size_t Count) requires (CDefaultConstructible<FElementType>)
|
||||||
{
|
{
|
||||||
if (Count == Impl.ListNum) return;
|
if (Count == Impl.ListNum) return;
|
||||||
|
|
||||||
if (Count < Impl.ListNum)
|
if (Count < Impl.ListNum)
|
||||||
{
|
{
|
||||||
Iterator First = End();
|
FIterator First = End();
|
||||||
|
|
||||||
Iteration::Advance(First, Count - Impl.ListNum);
|
Iteration::Advance(First, Count - Impl.ListNum);
|
||||||
|
|
||||||
@ -409,13 +409,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Resizes the container to contain 'Count' elements. Additional copies of 'InValue' are appended. */
|
/** Resizes the container to contain 'Count' elements. Additional copies of 'InValue' are appended. */
|
||||||
void SetNum(size_t Count, const ElementType& InValue) requires (CCopyConstructible<ElementType>)
|
void SetNum(size_t Count, const FElementType& InValue) requires (CCopyConstructible<FElementType>)
|
||||||
{
|
{
|
||||||
if (Count == Impl.ListNum) return;
|
if (Count == Impl.ListNum) return;
|
||||||
|
|
||||||
if (Count < Impl.ListNum)
|
if (Count < Impl.ListNum)
|
||||||
{
|
{
|
||||||
Iterator First = End();
|
FIterator First = End();
|
||||||
|
|
||||||
Iteration::Advance(First, Count - Impl.ListNum);
|
Iteration::Advance(First, Count - Impl.ListNum);
|
||||||
|
|
||||||
@ -445,16 +445,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return The iterator to the first or end element. */
|
/** @return The iterator to the first or end element. */
|
||||||
NODISCARD FORCEINLINE Iterator Begin() { return Iterator(Impl.HeadNode->NextNode); }
|
NODISCARD FORCEINLINE FIterator Begin() { return FIterator(Impl.HeadNode->NextNode); }
|
||||||
NODISCARD FORCEINLINE ConstIterator Begin() const { return ConstIterator(Impl.HeadNode->NextNode); }
|
NODISCARD FORCEINLINE FConstIterator Begin() const { return FConstIterator(Impl.HeadNode->NextNode); }
|
||||||
NODISCARD FORCEINLINE Iterator End() { return Iterator(Impl.HeadNode); }
|
NODISCARD FORCEINLINE FIterator End() { return FIterator(Impl.HeadNode); }
|
||||||
NODISCARD FORCEINLINE ConstIterator End() const { return ConstIterator(Impl.HeadNode); }
|
NODISCARD FORCEINLINE FConstIterator End() const { return FConstIterator(Impl.HeadNode); }
|
||||||
|
|
||||||
/** @return The reverse iterator to the first or end element. */
|
/** @return The reverse iterator to the first or end element. */
|
||||||
NODISCARD FORCEINLINE ReverseIterator RBegin() { return ReverseIterator(End()); }
|
NODISCARD FORCEINLINE FReverseIterator RBegin() { return FReverseIterator(End()); }
|
||||||
NODISCARD FORCEINLINE ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
|
NODISCARD FORCEINLINE FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
|
||||||
NODISCARD FORCEINLINE ReverseIterator REnd() { return ReverseIterator(Begin()); }
|
NODISCARD FORCEINLINE FReverseIterator REnd() { return FReverseIterator(Begin()); }
|
||||||
NODISCARD FORCEINLINE ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); }
|
NODISCARD FORCEINLINE FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
|
||||||
|
|
||||||
/** @return The number of elements in the container. */
|
/** @return The number of elements in the container. */
|
||||||
NODISCARD FORCEINLINE size_t Num() const { return Impl.ListNum; }
|
NODISCARD FORCEINLINE size_t Num() const { return Impl.ListNum; }
|
||||||
@ -463,7 +463,7 @@ public:
|
|||||||
NODISCARD FORCEINLINE bool IsEmpty() const { return Num() == 0; }
|
NODISCARD FORCEINLINE bool IsEmpty() const { return Num() == 0; }
|
||||||
|
|
||||||
/** @return true if the iterator is valid, false otherwise. */
|
/** @return true if the iterator is valid, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool IsValidIterator(ConstIterator Iter) const
|
NODISCARD FORCEINLINE bool IsValidIterator(FConstIterator Iter) const
|
||||||
{
|
{
|
||||||
FNode* Current = Impl.HeadNode;
|
FNode* Current = Impl.HeadNode;
|
||||||
|
|
||||||
@ -481,10 +481,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return The reference to the first or last element. */
|
/** @return The reference to the first or last element. */
|
||||||
NODISCARD FORCEINLINE ElementType& Front() { return *Begin(); }
|
NODISCARD FORCEINLINE FElementType& Front() { return *Begin(); }
|
||||||
NODISCARD FORCEINLINE const ElementType& Front() const { return *Begin(); }
|
NODISCARD FORCEINLINE const FElementType& Front() const { return *Begin(); }
|
||||||
NODISCARD FORCEINLINE ElementType& Back() { return *(End() - 1); }
|
NODISCARD FORCEINLINE FElementType& Back() { return *(End() - 1); }
|
||||||
NODISCARD FORCEINLINE const ElementType& Back() const { return *(End() - 1); }
|
NODISCARD FORCEINLINE const FElementType& Back() const { return *(End() - 1); }
|
||||||
|
|
||||||
/** Erases all elements from the container. After this call, Num() returns zero. */
|
/** Erases all elements from the container. After this call, Num() returns zero. */
|
||||||
void Reset()
|
void Reset()
|
||||||
@ -508,11 +508,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Overloads the GetTypeHash algorithm for TList. */
|
/** Overloads the GetTypeHash algorithm for TList. */
|
||||||
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TList& A) requires (CHashable<ElementType>)
|
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TList& A) requires (CHashable<FElementType>)
|
||||||
{
|
{
|
||||||
size_t Result = 0;
|
size_t Result = 0;
|
||||||
|
|
||||||
for (const ElementType& Element : A)
|
for (const FElementType& Element : A)
|
||||||
{
|
{
|
||||||
Result = HashCombine(Result, GetTypeHash(Element));
|
Result = HashCombine(Result, GetTypeHash(Element));
|
||||||
}
|
}
|
||||||
@ -535,7 +535,7 @@ private:
|
|||||||
{
|
{
|
||||||
FNode* PrevNode;
|
FNode* PrevNode;
|
||||||
FNode* NextNode;
|
FNode* NextNode;
|
||||||
ElementType Value;
|
FElementType Value;
|
||||||
|
|
||||||
FORCEINLINE FNode() = default;
|
FORCEINLINE FNode() = default;
|
||||||
|
|
||||||
@ -543,21 +543,21 @@ private:
|
|||||||
FORCEINLINE FNode(FInPlace, Ts&&... Args) : Value(Forward<Ts>(Args)...) { }
|
FORCEINLINE FNode(FInPlace, Ts&&... Args) : Value(Forward<Ts>(Args)...) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(CMultipleAllocator<AllocatorType, FNode>);
|
static_assert(CMultipleAllocator<FAllocatorType, FNode>);
|
||||||
|
|
||||||
ALLOCATOR_WRAPPER_BEGIN(AllocatorType, FNode, Impl)
|
ALLOCATOR_WRAPPER_BEGIN(FAllocatorType, FNode, Impl)
|
||||||
{
|
{
|
||||||
FNode* HeadNode;
|
FNode* HeadNode;
|
||||||
size_t ListNum;
|
size_t ListNum;
|
||||||
}
|
}
|
||||||
ALLOCATOR_WRAPPER_END(AllocatorType, FNode, Impl)
|
ALLOCATOR_WRAPPER_END(FAllocatorType, FNode, Impl)
|
||||||
|
|
||||||
template <bool bConst, typename U>
|
template <bool bConst, typename U>
|
||||||
class TIteratorImpl final
|
class TIteratorImpl final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TRemoveCV<T>;
|
using FElementType = TRemoveCV<T>;
|
||||||
|
|
||||||
FORCEINLINE TIteratorImpl() = default;
|
FORCEINLINE TIteratorImpl() = default;
|
||||||
|
|
||||||
|
@ -25,22 +25,22 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
|
|
||||||
using Reference = T&;
|
using FReference = T&;
|
||||||
using ConstReference = const T&;
|
using FConstReference = const T&;
|
||||||
|
|
||||||
using Iterator = TIteratorImpl<false>;
|
using FIterator = TIteratorImpl<false>;
|
||||||
using ConstIterator = TIteratorImpl<true >;
|
using FConstIterator = TIteratorImpl<true >;
|
||||||
|
|
||||||
using ReverseIterator = TReverseIterator< Iterator>;
|
using FReverseIterator = TReverseIterator< FIterator>;
|
||||||
using ConstReverseIterator = TReverseIterator<ConstIterator>;
|
using FConstReverseIterator = TReverseIterator<FConstIterator>;
|
||||||
|
|
||||||
static_assert(CContiguousIterator< Iterator>);
|
static_assert(CContiguousIterator< FIterator>);
|
||||||
static_assert(CContiguousIterator<ConstIterator>);
|
static_assert(CContiguousIterator<FConstIterator>);
|
||||||
|
|
||||||
/** Compares the contents of two arrays. */
|
/** Compares the contents of two arrays. */
|
||||||
NODISCARD friend constexpr bool operator==(const TStaticArray& LHS, const TStaticArray& RHS) requires (CWeaklyEqualityComparable<ElementType>)
|
NODISCARD friend constexpr bool operator==(const TStaticArray& LHS, const TStaticArray& RHS) requires (CWeaklyEqualityComparable<FElementType>)
|
||||||
{
|
{
|
||||||
if (LHS.Num() != RHS.Num()) return false;
|
if (LHS.Num() != RHS.Num()) return false;
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
||||||
NODISCARD friend constexpr auto operator<=>(const TStaticArray& LHS, const TStaticArray& RHS) requires (CSynthThreeWayComparable<ElementType>)
|
NODISCARD friend constexpr auto operator<=>(const TStaticArray& LHS, const TStaticArray& RHS) requires (CSynthThreeWayComparable<FElementType>)
|
||||||
{
|
{
|
||||||
const size_t NumToCompare = LHS.Num() < RHS.Num() ? LHS.Num() : RHS.Num();
|
const size_t NumToCompare = LHS.Num() < RHS.Num() ? LHS.Num() : RHS.Num();
|
||||||
|
|
||||||
@ -66,20 +66,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return The pointer to the underlying element storage. */
|
/** @return The pointer to the underlying element storage. */
|
||||||
NODISCARD FORCEINLINE constexpr ElementType* GetData() { return _; }
|
NODISCARD FORCEINLINE constexpr FElementType* GetData() { return _; }
|
||||||
NODISCARD FORCEINLINE constexpr const ElementType* GetData() const { return _; }
|
NODISCARD FORCEINLINE constexpr const FElementType* GetData() const { return _; }
|
||||||
|
|
||||||
/** @return The iterator to the first or end element. */
|
/** @return The iterator to the first or end element. */
|
||||||
NODISCARD FORCEINLINE constexpr Iterator Begin() { return Iterator(this, _); }
|
NODISCARD FORCEINLINE constexpr FIterator Begin() { return FIterator(this, _); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstIterator Begin() const { return ConstIterator(this, _); }
|
NODISCARD FORCEINLINE constexpr FConstIterator Begin() const { return FConstIterator(this, _); }
|
||||||
NODISCARD FORCEINLINE constexpr Iterator End() { return Iterator(this, _ + Num()); }
|
NODISCARD FORCEINLINE constexpr FIterator End() { return FIterator(this, _ + Num()); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstIterator End() const { return ConstIterator(this, _ + Num()); }
|
NODISCARD FORCEINLINE constexpr FConstIterator End() const { return FConstIterator(this, _ + Num()); }
|
||||||
|
|
||||||
/** @return The reverse iterator to the first or end element. */
|
/** @return The reverse iterator to the first or end element. */
|
||||||
NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() { return ReverseIterator(End()); }
|
NODISCARD FORCEINLINE constexpr FReverseIterator RBegin() { return FReverseIterator(End()); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
|
NODISCARD FORCEINLINE constexpr FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
|
||||||
NODISCARD FORCEINLINE constexpr ReverseIterator REnd() { return ReverseIterator(Begin()); }
|
NODISCARD FORCEINLINE constexpr FReverseIterator REnd() { return FReverseIterator(Begin()); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); }
|
NODISCARD FORCEINLINE constexpr FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
|
||||||
|
|
||||||
/** @return The number of elements in the container. */
|
/** @return The number of elements in the container. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t Num() const { return N; }
|
NODISCARD FORCEINLINE constexpr size_t Num() const { return N; }
|
||||||
@ -88,24 +88,24 @@ public:
|
|||||||
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; }
|
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; }
|
||||||
|
|
||||||
/** @return true if the iterator is valid, false otherwise. */
|
/** @return true if the iterator is valid, false otherwise. */
|
||||||
NODISCARD FORCEINLINE constexpr bool IsValidIterator(ConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
|
NODISCARD FORCEINLINE constexpr bool IsValidIterator(FConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
|
||||||
|
|
||||||
/** @return The reference to the requested element. */
|
/** @return The reference to the requested element. */
|
||||||
NODISCARD FORCEINLINE constexpr ElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return _[Index]; }
|
NODISCARD FORCEINLINE constexpr FElementType& operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return _[Index]; }
|
||||||
NODISCARD FORCEINLINE constexpr const ElementType& operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return _[Index]; }
|
NODISCARD FORCEINLINE constexpr const FElementType& operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return _[Index]; }
|
||||||
|
|
||||||
/** @return The reference to the first or last element. */
|
/** @return The reference to the first or last element. */
|
||||||
NODISCARD FORCEINLINE constexpr ElementType& Front() { return *Begin(); }
|
NODISCARD FORCEINLINE constexpr FElementType& Front() { return *Begin(); }
|
||||||
NODISCARD FORCEINLINE constexpr const ElementType& Front() const { return *Begin(); }
|
NODISCARD FORCEINLINE constexpr const FElementType& Front() const { return *Begin(); }
|
||||||
NODISCARD FORCEINLINE constexpr ElementType& Back() { return *(End() - 1); }
|
NODISCARD FORCEINLINE constexpr FElementType& Back() { return *(End() - 1); }
|
||||||
NODISCARD FORCEINLINE constexpr const ElementType& Back() const { return *(End() - 1); }
|
NODISCARD FORCEINLINE constexpr const FElementType& Back() const { return *(End() - 1); }
|
||||||
|
|
||||||
/** Overloads the GetTypeHash algorithm for TStaticArray. */
|
/** Overloads the GetTypeHash algorithm for TStaticArray. */
|
||||||
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(const TStaticArray& A) requires (CHashable<ElementType>)
|
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(const TStaticArray& A) requires (CHashable<FElementType>)
|
||||||
{
|
{
|
||||||
size_t Result = 0;
|
size_t Result = 0;
|
||||||
|
|
||||||
for (ConstIterator Iter = A.Begin(); Iter != A.End(); ++Iter)
|
for (FConstIterator Iter = A.Begin(); Iter != A.End(); ++Iter)
|
||||||
{
|
{
|
||||||
Result = HashCombine(Result, GetTypeHash(*Iter));
|
Result = HashCombine(Result, GetTypeHash(*Iter));
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Overloads the Swap algorithm for TStaticArray. */
|
/** Overloads the Swap algorithm for TStaticArray. */
|
||||||
friend FORCEINLINE constexpr void Swap(TStaticArray& A, TStaticArray& B) requires (CSwappable<ElementType>) { Swap(A._, B._); }
|
friend FORCEINLINE constexpr void Swap(TStaticArray& A, TStaticArray& B) requires (CSwappable<FElementType>) { Swap(A._, B._); }
|
||||||
|
|
||||||
ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT
|
ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ private:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TRemoveCV<T>;
|
using FElementType = TRemoveCV<T>;
|
||||||
|
|
||||||
FORCEINLINE constexpr TIteratorImpl() = default;
|
FORCEINLINE constexpr TIteratorImpl() = default;
|
||||||
|
|
||||||
@ -224,6 +224,8 @@ NAMESPACE_MODULE_END(Utility)
|
|||||||
NAMESPACE_MODULE_END(Redcraft)
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
NAMESPACE_REDCRAFT_END
|
NAMESPACE_REDCRAFT_END
|
||||||
|
|
||||||
|
// ReSharper disable CppInconsistentNaming
|
||||||
|
|
||||||
NAMESPACE_STD_BEGIN
|
NAMESPACE_STD_BEGIN
|
||||||
|
|
||||||
// Support structure binding, should not be directly used.
|
// Support structure binding, should not be directly used.
|
||||||
@ -245,3 +247,5 @@ template <size_t Index, typename T, size_t N> FORCEINLINE constexpr decltype(aut
|
|||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
NAMESPACE_MODULE_END(Redcraft)
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
NAMESPACE_REDCRAFT_END
|
NAMESPACE_REDCRAFT_END
|
||||||
|
|
||||||
|
// ReSharper restore CppInconsistentNaming
|
||||||
|
@ -37,22 +37,22 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using BlockType = InBlockType;
|
using FBlockType = InBlockType;
|
||||||
using ElementType = bool;
|
using FElementType = bool;
|
||||||
|
|
||||||
class Reference;
|
class FReference;
|
||||||
using ConstReference = bool;
|
using FConstReference = bool;
|
||||||
|
|
||||||
using Iterator = TIteratorImpl<false>;
|
using FIterator = TIteratorImpl<false>;
|
||||||
using ConstIterator = TIteratorImpl<true >;
|
using FConstIterator = TIteratorImpl<true >;
|
||||||
|
|
||||||
using ReverseIterator = TReverseIterator< Iterator>;
|
using FReverseIterator = TReverseIterator< FIterator>;
|
||||||
using ConstReverseIterator = TReverseIterator<ConstIterator>;
|
using FConstReverseIterator = TReverseIterator<FConstIterator>;
|
||||||
|
|
||||||
static_assert(CRandomAccessIterator< Iterator>);
|
static_assert(CRandomAccessIterator< FIterator>);
|
||||||
static_assert(CRandomAccessIterator<ConstIterator>);
|
static_assert(CRandomAccessIterator<FConstIterator>);
|
||||||
|
|
||||||
static constexpr size_t BlockWidth = sizeof(BlockType) * 8;
|
static constexpr size_t BlockWidth = sizeof(FBlockType) * 8;
|
||||||
|
|
||||||
/** Default constructor. Constructs an empty bitset. */
|
/** Default constructor. Constructs an empty bitset. */
|
||||||
FORCEINLINE constexpr TStaticBitset() = default;
|
FORCEINLINE constexpr TStaticBitset() = default;
|
||||||
@ -60,38 +60,38 @@ public:
|
|||||||
/** Constructs a bitset from an integer. */
|
/** Constructs a bitset from an integer. */
|
||||||
constexpr TStaticBitset(uint64 InValue)
|
constexpr TStaticBitset(uint64 InValue)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
|
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
|
||||||
|
|
||||||
if constexpr (sizeof(BlockType) == sizeof(uint8))
|
if constexpr (sizeof(FBlockType) == sizeof(uint8))
|
||||||
{
|
{
|
||||||
if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
|
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0);
|
||||||
if constexpr (N > 8) Impl[1] = static_cast<BlockType>(InValue >> 8);
|
if constexpr (N > 8) Impl[1] = static_cast<FBlockType>(InValue >> 8);
|
||||||
if constexpr (N > 16) Impl[2] = static_cast<BlockType>(InValue >> 16);
|
if constexpr (N > 16) Impl[2] = static_cast<FBlockType>(InValue >> 16);
|
||||||
if constexpr (N > 24) Impl[3] = static_cast<BlockType>(InValue >> 24);
|
if constexpr (N > 24) Impl[3] = static_cast<FBlockType>(InValue >> 24);
|
||||||
if constexpr (N > 32) Impl[4] = static_cast<BlockType>(InValue >> 32);
|
if constexpr (N > 32) Impl[4] = static_cast<FBlockType>(InValue >> 32);
|
||||||
if constexpr (N > 40) Impl[5] = static_cast<BlockType>(InValue >> 40);
|
if constexpr (N > 40) Impl[5] = static_cast<FBlockType>(InValue >> 40);
|
||||||
if constexpr (N > 48) Impl[6] = static_cast<BlockType>(InValue >> 48);
|
if constexpr (N > 48) Impl[6] = static_cast<FBlockType>(InValue >> 48);
|
||||||
if constexpr (N > 56) Impl[7] = static_cast<BlockType>(InValue >> 56);
|
if constexpr (N > 56) Impl[7] = static_cast<FBlockType>(InValue >> 56);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint16))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
|
||||||
{
|
{
|
||||||
if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
|
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0);
|
||||||
if constexpr (N > 16) Impl[1] = static_cast<BlockType>(InValue >> 16);
|
if constexpr (N > 16) Impl[1] = static_cast<FBlockType>(InValue >> 16);
|
||||||
if constexpr (N > 32) Impl[2] = static_cast<BlockType>(InValue >> 32);
|
if constexpr (N > 32) Impl[2] = static_cast<FBlockType>(InValue >> 32);
|
||||||
if constexpr (N > 48) Impl[3] = static_cast<BlockType>(InValue >> 48);
|
if constexpr (N > 48) Impl[3] = static_cast<FBlockType>(InValue >> 48);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint32))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
|
||||||
{
|
{
|
||||||
if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
|
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0);
|
||||||
if constexpr (N > 32) Impl[1] = static_cast<BlockType>(InValue >> 32);
|
if constexpr (N > 32) Impl[1] = static_cast<FBlockType>(InValue >> 32);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint64))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
|
||||||
{
|
{
|
||||||
if constexpr (N > 0) Impl[0] = static_cast<BlockType>(InValue >> 0);
|
if constexpr (N > 0) Impl[0] = static_cast<FBlockType>(InValue >> 0);
|
||||||
}
|
}
|
||||||
else check_no_entry();
|
else check_no_entry();
|
||||||
|
|
||||||
constexpr size_t BlockInteger = sizeof(uint64) / sizeof(BlockType);
|
constexpr size_t BlockInteger = sizeof(uint64) / sizeof(FBlockType);
|
||||||
|
|
||||||
if constexpr ((N + BlockWidth - 1) / BlockWidth <= BlockInteger) return;
|
if constexpr ((N + BlockWidth - 1) / BlockWidth <= BlockInteger) return;
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ public:
|
|||||||
if (LHS.Impl[Index] != RHS.Impl[Index]) return false;
|
if (LHS.Impl[Index] != RHS.Impl[Index]) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = LHS.Num() % BlockWidth != 0 ? (1ull << LHS.Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = LHS.Num() % BlockWidth != 0 ? (1ull << LHS.Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
return (LHS.Impl[LHS.NumBlocks() - 1] & LastBlockBitmask) == (RHS.Impl[LHS.NumBlocks() - 1] & LastBlockBitmask);
|
return (LHS.Impl[LHS.NumBlocks() - 1] & LastBlockBitmask) == (RHS.Impl[LHS.NumBlocks() - 1] & LastBlockBitmask);
|
||||||
}
|
}
|
||||||
@ -269,7 +269,7 @@ public:
|
|||||||
if (Impl[Index] != -1) return false;
|
if (Impl[Index] != -1) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
return (Impl[NumBlocks() - 1] | ~LastBlockBitmask) == -1;
|
return (Impl[NumBlocks() - 1] | ~LastBlockBitmask) == -1;
|
||||||
}
|
}
|
||||||
@ -284,7 +284,7 @@ public:
|
|||||||
if (Impl[Index] != 0) return true;
|
if (Impl[Index] != 0) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
return (Impl[NumBlocks() - 1] & LastBlockBitmask) != 0;
|
return (Impl[NumBlocks() - 1] & LastBlockBitmask) != 0;
|
||||||
}
|
}
|
||||||
@ -299,24 +299,24 @@ public:
|
|||||||
|
|
||||||
size_t Result = 0;
|
size_t Result = 0;
|
||||||
|
|
||||||
constexpr auto BlockCount = [](BlockType Block) constexpr
|
constexpr auto BlockCount = [](FBlockType Block) constexpr
|
||||||
{
|
{
|
||||||
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
|
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
|
||||||
|
|
||||||
if constexpr (sizeof(BlockType) == sizeof(uint8))
|
if constexpr (sizeof(FBlockType) == sizeof(uint8))
|
||||||
{
|
{
|
||||||
Block = (Block & 0x55ull) + ((Block >> 1) & 0x55ull);
|
Block = (Block & 0x55ull) + ((Block >> 1) & 0x55ull);
|
||||||
Block = (Block & 0x33ull) + ((Block >> 2) & 0x33ull);
|
Block = (Block & 0x33ull) + ((Block >> 2) & 0x33ull);
|
||||||
Block = (Block & 0x0Full) + ((Block >> 4) & 0x0Full);
|
Block = (Block & 0x0Full) + ((Block >> 4) & 0x0Full);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint16))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
|
||||||
{
|
{
|
||||||
Block = (Block & 0x5555ull) + ((Block >> 1) & 0x5555ull);
|
Block = (Block & 0x5555ull) + ((Block >> 1) & 0x5555ull);
|
||||||
Block = (Block & 0x3333ull) + ((Block >> 2) & 0x3333ull);
|
Block = (Block & 0x3333ull) + ((Block >> 2) & 0x3333ull);
|
||||||
Block = (Block & 0x0F0Full) + ((Block >> 4) & 0x0F0Full);
|
Block = (Block & 0x0F0Full) + ((Block >> 4) & 0x0F0Full);
|
||||||
Block = (Block & 0x00FFull) + ((Block >> 8) & 0x00FFull);
|
Block = (Block & 0x00FFull) + ((Block >> 8) & 0x00FFull);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint32))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
|
||||||
{
|
{
|
||||||
Block = (Block & 0x55555555ull) + ((Block >> 1) & 0x55555555ull);
|
Block = (Block & 0x55555555ull) + ((Block >> 1) & 0x55555555ull);
|
||||||
Block = (Block & 0x33333333ull) + ((Block >> 2) & 0x33333333ull);
|
Block = (Block & 0x33333333ull) + ((Block >> 2) & 0x33333333ull);
|
||||||
@ -324,7 +324,7 @@ public:
|
|||||||
Block = (Block & 0x00FF00FFull) + ((Block >> 8) & 0x00FF00FFull);
|
Block = (Block & 0x00FF00FFull) + ((Block >> 8) & 0x00FF00FFull);
|
||||||
Block = (Block & 0x0000FFFFull) + ((Block >> 16) & 0x0000FFFFull);
|
Block = (Block & 0x0000FFFFull) + ((Block >> 16) & 0x0000FFFFull);
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint64))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
|
||||||
{
|
{
|
||||||
Block = (Block & 0x5555555555555555ull) + ((Block >> 1) & 0x5555555555555555ull);
|
Block = (Block & 0x5555555555555555ull) + ((Block >> 1) & 0x5555555555555555ull);
|
||||||
Block = (Block & 0x3333333333333333ull) + ((Block >> 2) & 0x3333333333333333ull);
|
Block = (Block & 0x3333333333333333ull) + ((Block >> 2) & 0x3333333333333333ull);
|
||||||
@ -343,7 +343,7 @@ public:
|
|||||||
Result += BlockCount(Impl[Index]);
|
Result += BlockCount(Impl[Index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
Result += BlockCount(Impl[NumBlocks() - 1] & LastBlockBitmask);
|
Result += BlockCount(Impl[NumBlocks() - 1] & LastBlockBitmask);
|
||||||
|
|
||||||
@ -355,7 +355,7 @@ public:
|
|||||||
{
|
{
|
||||||
for (size_t Index = 0; Index != NumBlocks(); ++Index)
|
for (size_t Index = 0; Index != NumBlocks(); ++Index)
|
||||||
{
|
{
|
||||||
Impl[Index] = static_cast<BlockType>(InValue ? -1 : 0);
|
Impl[Index] = static_cast<FBlockType>(InValue ? -1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@ -387,20 +387,20 @@ public:
|
|||||||
{
|
{
|
||||||
for (size_t Index = 64 / BlockWidth; Index < NumBlocks() - 1; ++Index)
|
for (size_t Index = 64 / BlockWidth; Index < NumBlocks() - 1; ++Index)
|
||||||
{
|
{
|
||||||
checkf(Impl.Pointer[Index] != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
|
checkf(Impl[Index] != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = Num() % BlockWidth != 0 ? (1ull << Num() % BlockWidth) - 1 : -1;
|
||||||
const BlockType LastBlock = Impl.Pointer[NumBlocks() - 1] & LastBlockBitmask;
|
const FBlockType LastBlock = Impl[NumBlocks() - 1] & LastBlockBitmask;
|
||||||
|
|
||||||
checkf(LastBlock != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
|
checkf(LastBlock != 0, TEXT("The bitset can not be represented in uint64. Please check Num()."));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 Result = 0;
|
uint64 Result = 0;
|
||||||
|
|
||||||
static_assert(sizeof(BlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
|
static_assert(sizeof(FBlockType) <= sizeof(uint64), "The block width of TStaticBitset is unexpected");
|
||||||
|
|
||||||
if constexpr (sizeof(BlockType) == sizeof(uint8))
|
if constexpr (sizeof(FBlockType) == sizeof(uint8))
|
||||||
{
|
{
|
||||||
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
|
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
|
||||||
if constexpr (N > 8) Result |= static_cast<uint64>(Impl[1]) << 8;
|
if constexpr (N > 8) Result |= static_cast<uint64>(Impl[1]) << 8;
|
||||||
@ -411,19 +411,19 @@ public:
|
|||||||
if constexpr (N > 48) Result |= static_cast<uint64>(Impl[6]) << 48;
|
if constexpr (N > 48) Result |= static_cast<uint64>(Impl[6]) << 48;
|
||||||
if constexpr (N > 56) Result |= static_cast<uint64>(Impl[7]) << 56;
|
if constexpr (N > 56) Result |= static_cast<uint64>(Impl[7]) << 56;
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint16))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint16))
|
||||||
{
|
{
|
||||||
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
|
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
|
||||||
if constexpr (N > 16) Result |= static_cast<uint64>(Impl[1]) << 16;
|
if constexpr (N > 16) Result |= static_cast<uint64>(Impl[1]) << 16;
|
||||||
if constexpr (N > 32) Result |= static_cast<uint64>(Impl[2]) << 32;
|
if constexpr (N > 32) Result |= static_cast<uint64>(Impl[2]) << 32;
|
||||||
if constexpr (N > 48) Result |= static_cast<uint64>(Impl[3]) << 48;
|
if constexpr (N > 48) Result |= static_cast<uint64>(Impl[3]) << 48;
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint32))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint32))
|
||||||
{
|
{
|
||||||
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
|
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
|
||||||
if constexpr (N > 32) Result |= static_cast<uint64>(Impl[1]) << 32;
|
if constexpr (N > 32) Result |= static_cast<uint64>(Impl[1]) << 32;
|
||||||
}
|
}
|
||||||
else if constexpr (sizeof(BlockType) == sizeof(uint64))
|
else if constexpr (sizeof(FBlockType) == sizeof(uint64))
|
||||||
{
|
{
|
||||||
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
|
if constexpr (N > 0) Result |= static_cast<uint64>(Impl[0]) << 0;
|
||||||
}
|
}
|
||||||
@ -435,20 +435,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return The pointer to the underlying element storage. */
|
/** @return The pointer to the underlying element storage. */
|
||||||
NODISCARD FORCEINLINE constexpr BlockType* GetData() { return Impl; }
|
NODISCARD FORCEINLINE constexpr FBlockType* GetData() { return Impl; }
|
||||||
NODISCARD FORCEINLINE constexpr const BlockType* GetData() const { return Impl; }
|
NODISCARD FORCEINLINE constexpr const FBlockType* GetData() const { return Impl; }
|
||||||
|
|
||||||
/** @return The iterator to the first or end bit. */
|
/** @return The iterator to the first or end bit. */
|
||||||
NODISCARD FORCEINLINE constexpr Iterator Begin() { return Iterator(this, Impl, 0); }
|
NODISCARD FORCEINLINE constexpr FIterator Begin() { return FIterator(this, Impl, 0); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstIterator Begin() const { return ConstIterator(this, Impl, 0); }
|
NODISCARD FORCEINLINE constexpr FConstIterator Begin() const { return FConstIterator(this, Impl, 0); }
|
||||||
NODISCARD FORCEINLINE constexpr Iterator End() { return Iterator(this, Impl, Num()); }
|
NODISCARD FORCEINLINE constexpr FIterator End() { return FIterator(this, Impl, Num()); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstIterator End() const { return ConstIterator(this, Impl, Num()); }
|
NODISCARD FORCEINLINE constexpr FConstIterator End() const { return FConstIterator(this, Impl, Num()); }
|
||||||
|
|
||||||
/** @return The reverse iterator to the first or end bit. */
|
/** @return The reverse iterator to the first or end bit. */
|
||||||
NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() { return ReverseIterator(End()); }
|
NODISCARD FORCEINLINE constexpr FReverseIterator RBegin() { return FReverseIterator(End()); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); }
|
NODISCARD FORCEINLINE constexpr FConstReverseIterator RBegin() const { return FConstReverseIterator(End()); }
|
||||||
NODISCARD FORCEINLINE constexpr ReverseIterator REnd() { return ReverseIterator(Begin()); }
|
NODISCARD FORCEINLINE constexpr FReverseIterator REnd() { return FReverseIterator(Begin()); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); }
|
NODISCARD FORCEINLINE constexpr FConstReverseIterator REnd() const { return FConstReverseIterator(Begin()); }
|
||||||
|
|
||||||
/** @return The number of bits in the bitset. */
|
/** @return The number of bits in the bitset. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t Num() const { return N; }
|
NODISCARD FORCEINLINE constexpr size_t Num() const { return N; }
|
||||||
@ -460,17 +460,17 @@ public:
|
|||||||
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; }
|
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return Num() == 0; }
|
||||||
|
|
||||||
/** @return true if the iterator is valid, false otherwise. */
|
/** @return true if the iterator is valid, false otherwise. */
|
||||||
NODISCARD FORCEINLINE constexpr bool IsValidIterator(ConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
|
NODISCARD FORCEINLINE constexpr bool IsValidIterator(FConstIterator Iter) const { return Begin() <= Iter && Iter <= End(); }
|
||||||
|
|
||||||
/** @return The reference to the requested bit. */
|
/** @return The reference to the requested bit. */
|
||||||
NODISCARD FORCEINLINE constexpr Reference operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
|
NODISCARD FORCEINLINE constexpr FReference operator[](size_t Index) { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
|
NODISCARD FORCEINLINE constexpr FConstReference operator[](size_t Index) const { checkf(Index < Num(), TEXT("Read access violation. Please check IsValidIterator().")); return *(Begin() + Index); }
|
||||||
|
|
||||||
/** @return The reference to the first or last bit. */
|
/** @return The reference to the first or last bit. */
|
||||||
NODISCARD FORCEINLINE constexpr Reference Front() { return *Begin(); }
|
NODISCARD FORCEINLINE constexpr FReference Front() { return *Begin(); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstReference Front() const { return *Begin(); }
|
NODISCARD FORCEINLINE constexpr FConstReference Front() const { return *Begin(); }
|
||||||
NODISCARD FORCEINLINE constexpr Reference Back() { return *(End() - 1); }
|
NODISCARD FORCEINLINE constexpr FReference Back() { return *(End() - 1); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstReference Back() const { return *(End() - 1); }
|
NODISCARD FORCEINLINE constexpr FConstReference Back() const { return *(End() - 1); }
|
||||||
|
|
||||||
/** Overloads the GetTypeHash algorithm for TStaticBitset. */
|
/** Overloads the GetTypeHash algorithm for TStaticBitset. */
|
||||||
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(const TStaticBitset& A)
|
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(const TStaticBitset& A)
|
||||||
@ -484,7 +484,7 @@ public:
|
|||||||
Result = HashCombine(Result, GetTypeHash(A.Impl[Index]));
|
Result = HashCombine(Result, GetTypeHash(A.Impl[Index]));
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockType LastBlockBitmask = A.Num() % BlockWidth != 0 ? (1ull << A.Num() % BlockWidth) - 1 : -1;
|
const FBlockType LastBlockBitmask = A.Num() % BlockWidth != 0 ? (1ull << A.Num() % BlockWidth) - 1 : -1;
|
||||||
|
|
||||||
return HashCombine(Result, GetTypeHash(A.Impl[A.NumBlocks() - 1] & LastBlockBitmask));
|
return HashCombine(Result, GetTypeHash(A.Impl[A.NumBlocks() - 1] & LastBlockBitmask));
|
||||||
}
|
}
|
||||||
@ -496,21 +496,21 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
BlockType Impl[N != 0 ? (N + BlockWidth - 1) / BlockWidth : 1];
|
FBlockType Impl[N != 0 ? (N + BlockWidth - 1) / BlockWidth : 1];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class Reference final : private FSingleton
|
class FReference final : private FSingleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FORCEINLINE constexpr Reference& operator=(bool InValue) { Data = (Data & ~Mask) | (InValue ? Mask : 0); return *this; }
|
FORCEINLINE constexpr FReference& operator=(bool InValue) { Data = (Data & ~Mask) | (InValue ? Mask : 0); return *this; }
|
||||||
|
|
||||||
FORCEINLINE constexpr Reference& operator=(const Reference& InValue) { *this = static_cast<bool>(InValue); return *this; }
|
FORCEINLINE constexpr FReference& operator=(const FReference& InValue) { *this = static_cast<bool>(InValue); return *this; }
|
||||||
|
|
||||||
FORCEINLINE constexpr Reference& operator&=(bool InValue) { Data &= InValue ? -1 : ~Mask; return *this; }
|
FORCEINLINE constexpr FReference& operator&=(bool InValue) { Data &= InValue ? -1 : ~Mask; return *this; }
|
||||||
FORCEINLINE constexpr Reference& operator|=(bool InValue) { Data |= InValue ? Mask : 0; return *this; }
|
FORCEINLINE constexpr FReference& operator|=(bool InValue) { Data |= InValue ? Mask : 0; return *this; }
|
||||||
FORCEINLINE constexpr Reference& operator^=(bool InValue) { *this = InValue ^ *this; return *this; }
|
FORCEINLINE constexpr FReference& operator^=(bool InValue) { *this = InValue ^ *this; return *this; }
|
||||||
|
|
||||||
FORCEINLINE constexpr bool operator~() const { return !*this; }
|
FORCEINLINE constexpr bool operator~() const { return !*this; }
|
||||||
|
|
||||||
@ -518,14 +518,14 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
FORCEINLINE constexpr Reference(BlockType& InData, BlockType InMask)
|
FORCEINLINE constexpr FReference(FBlockType& InData, FBlockType InMask)
|
||||||
: Data(InData), Mask(InMask)
|
: Data(InData), Mask(InMask)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
BlockType& Data;
|
FBlockType& Data;
|
||||||
BlockType Mask;
|
FBlockType Mask;
|
||||||
|
|
||||||
friend Iterator;
|
friend FIterator;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -538,7 +538,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = bool;
|
using FElementType = bool;
|
||||||
|
|
||||||
FORCEINLINE constexpr TIteratorImpl() = default;
|
FORCEINLINE constexpr TIteratorImpl() = default;
|
||||||
|
|
||||||
@ -561,8 +561,8 @@ private:
|
|||||||
|
|
||||||
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TIteratorImpl& LHS, const TIteratorImpl& RHS) { check(LHS.Pointer == RHS.Pointer); return LHS.BitOffset <=> RHS.BitOffset; }
|
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TIteratorImpl& LHS, const TIteratorImpl& RHS) { check(LHS.Pointer == RHS.Pointer); return LHS.BitOffset <=> RHS.BitOffset; }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr Reference operator*() const requires (!bConst) { CheckThis(true); return Reference(*(Pointer + BitOffset / BlockWidth), 1ull << BitOffset % BlockWidth); }
|
NODISCARD FORCEINLINE constexpr FReference operator*() const requires (!bConst) { CheckThis(true); return FReference(*(Pointer + BitOffset / BlockWidth), 1ull << BitOffset % BlockWidth); }
|
||||||
NODISCARD FORCEINLINE constexpr ConstReference operator*() const requires ( bConst) { CheckThis(true); return (*(Pointer + BitOffset / BlockWidth) & (1ull << BitOffset % BlockWidth)); }
|
NODISCARD FORCEINLINE constexpr FConstReference operator*() const requires ( bConst) { CheckThis(true); return (*(Pointer + BitOffset / BlockWidth) & (1ull << BitOffset % BlockWidth)); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr auto operator[](ptrdiff Index) const { TIteratorImpl Temp = *this + Index; return *Temp; }
|
NODISCARD FORCEINLINE constexpr auto operator[](ptrdiff Index) const { TIteratorImpl Temp = *this + Index; return *Temp; }
|
||||||
|
|
||||||
@ -588,17 +588,17 @@ private:
|
|||||||
const TStaticBitset* Owner = nullptr;
|
const TStaticBitset* Owner = nullptr;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
using BlockPtr = TConditional<bConst, const BlockType*, BlockType*>;
|
using FBlockPtr = TConditional<bConst, const FBlockType*, FBlockType*>;
|
||||||
|
|
||||||
BlockPtr Pointer = nullptr;
|
FBlockPtr Pointer = nullptr;
|
||||||
size_t BitOffset = 0;
|
size_t BitOffset = 0;
|
||||||
|
|
||||||
# if DO_CHECK
|
# if DO_CHECK
|
||||||
FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, BlockPtr InPointer, size_t Offset)
|
FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, FBlockPtr InPointer, size_t Offset)
|
||||||
: Owner(InContainer), Pointer(InPointer), BitOffset(Offset)
|
: Owner(InContainer), Pointer(InPointer), BitOffset(Offset)
|
||||||
{ }
|
{ }
|
||||||
# else
|
# else
|
||||||
FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, BlockPtr InPointer, size_t Offset)
|
FORCEINLINE constexpr TIteratorImpl(const TStaticBitset* InContainer, FBlockPtr InPointer, size_t Offset)
|
||||||
: Pointer(InPointer), BitOffset(Offset)
|
: Pointer(InPointer), BitOffset(Offset)
|
||||||
{ }
|
{ }
|
||||||
# endif
|
# endif
|
||||||
|
@ -33,7 +33,7 @@ struct IBidirectionalIterator /* : IForwardIterator<T> */
|
|||||||
{
|
{
|
||||||
// ~Begin CForwardIterator.
|
// ~Begin CForwardIterator.
|
||||||
|
|
||||||
using ElementType = TRemoveCVRef<T>;
|
using FElementType = TRemoveCVRef<T>;
|
||||||
|
|
||||||
IBidirectionalIterator();
|
IBidirectionalIterator();
|
||||||
IBidirectionalIterator(const IBidirectionalIterator&);
|
IBidirectionalIterator(const IBidirectionalIterator&);
|
||||||
|
@ -35,7 +35,7 @@ struct IContiguousIterator /* : IRandomAccessIterator<T> */
|
|||||||
{
|
{
|
||||||
// ~Begin CRandomAccessIterator.
|
// ~Begin CRandomAccessIterator.
|
||||||
|
|
||||||
using ElementType = TRemoveCVRef<T>;
|
using FElementType = TRemoveCVRef<T>;
|
||||||
|
|
||||||
IContiguousIterator();
|
IContiguousIterator();
|
||||||
IContiguousIterator(const IContiguousIterator&);
|
IContiguousIterator(const IContiguousIterator&);
|
||||||
|
@ -19,7 +19,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
|
|||||||
NAMESPACE_PRIVATE_BEGIN
|
NAMESPACE_PRIVATE_BEGIN
|
||||||
|
|
||||||
template <typename T> class TCountedIteratorImpl { };
|
template <typename T> class TCountedIteratorImpl { };
|
||||||
template <CIndirectlyReadable T> class TCountedIteratorImpl<T> { public: using ElementType = TIteratorElement<T>; };
|
template <CIndirectlyReadable T> class TCountedIteratorImpl<T> { public: using FElementType = TIteratorElement<T>; };
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ class TCountedIterator final : public NAMESPACE_PRIVATE::TCountedIteratorImpl<I>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using IteratorType = I;
|
using FIteratorType = I;
|
||||||
|
|
||||||
# if DO_CHECK
|
# if DO_CHECK
|
||||||
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<I>) : Length(1), MaxLength(0) { }
|
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<I>) : Length(1), MaxLength(0) { }
|
||||||
@ -48,7 +48,7 @@ public:
|
|||||||
FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator&&) = default;
|
FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator&&) = default;
|
||||||
FORCEINLINE constexpr ~TCountedIterator() = default;
|
FORCEINLINE constexpr ~TCountedIterator() = default;
|
||||||
|
|
||||||
FORCEINLINE constexpr explicit TCountedIterator(IteratorType InValue, ptrdiff N) : Current(MoveTemp(InValue)) { check_code({ MaxLength = N; }); }
|
FORCEINLINE constexpr explicit TCountedIterator(FIteratorType InValue, ptrdiff N) : Current(MoveTemp(InValue)) { check_code({ MaxLength = N; }); }
|
||||||
|
|
||||||
template <CInputOrOutputIterator J> requires (!CSameAs<I, J> && CConstructibleFrom<I, const J&>)
|
template <CInputOrOutputIterator J> requires (!CSameAs<I, J> && CConstructibleFrom<I, const J&>)
|
||||||
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, I>) TCountedIterator(const TCountedIterator<J>& InValue)
|
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, I>) TCountedIterator(const TCountedIterator<J>& InValue)
|
||||||
@ -106,13 +106,13 @@ public:
|
|||||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { LHS.CheckThis(); return -LHS.Num(); }
|
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { LHS.CheckThis(); return -LHS.Num(); }
|
||||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { RHS.CheckThis(); return RHS.Num(); }
|
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { RHS.CheckThis(); return RHS.Num(); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { CheckThis(); return Current; }
|
NODISCARD FORCEINLINE constexpr const FIteratorType& GetBase() const& { CheckThis(); return Current; }
|
||||||
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { CheckThis(); return MoveTemp(Current); }
|
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { CheckThis(); return MoveTemp(Current); }
|
||||||
NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; }
|
NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
IteratorType Current;
|
FIteratorType Current;
|
||||||
ptrdiff Length;
|
ptrdiff Length;
|
||||||
|
|
||||||
# if DO_CHECK
|
# if DO_CHECK
|
||||||
|
@ -24,7 +24,7 @@ struct IForwardIterator /* : IInputIterator<T>, IIncrementable, ISentinelFor<IFo
|
|||||||
{
|
{
|
||||||
// ~Begin CInputIterator.
|
// ~Begin CInputIterator.
|
||||||
|
|
||||||
using ElementType = TRemoveCVRef<T>;
|
using FElementType = TRemoveCVRef<T>;
|
||||||
|
|
||||||
// ~End CInputIterator.
|
// ~End CInputIterator.
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ NODISCARD FORCEINLINE constexpr auto MakeBackInserter(C& Container)
|
|||||||
|
|
||||||
/** Creates an iterator adapter inserted in the container. */
|
/** Creates an iterator adapter inserted in the container. */
|
||||||
template <typename C>
|
template <typename C>
|
||||||
NODISCARD FORCEINLINE constexpr auto MakeInserter(C& Container, const typename C::ConstIterator& InIter)
|
NODISCARD FORCEINLINE constexpr auto MakeInserter(C& Container, const typename C::FConstIterator& InIter)
|
||||||
{
|
{
|
||||||
return NAMESPACE_PRIVATE::TInsertIterator([&Container, Iter = InIter]<typename T>(T&& A) mutable { Iter = Container.Insert(Iter, Forward<T>(A)); });
|
return NAMESPACE_PRIVATE::TInsertIterator([&Container, Iter = InIter]<typename T>(T&& A) mutable { Iter = Container.Insert(Iter, Forward<T>(A)); });
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,9 @@ class TMoveIterator final
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using IteratorType = I;
|
using FIteratorType = I;
|
||||||
|
|
||||||
using ElementType = TIteratorElement<I>;
|
using FElementType = TIteratorElement<I>;
|
||||||
|
|
||||||
FORCEINLINE constexpr TMoveIterator() requires (CDefaultConstructible<I>) = default;
|
FORCEINLINE constexpr TMoveIterator() requires (CDefaultConstructible<I>) = default;
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ public:
|
|||||||
FORCEINLINE constexpr TMoveIterator& operator=(TMoveIterator&&) = default;
|
FORCEINLINE constexpr TMoveIterator& operator=(TMoveIterator&&) = default;
|
||||||
FORCEINLINE constexpr ~TMoveIterator() = default;
|
FORCEINLINE constexpr ~TMoveIterator() = default;
|
||||||
|
|
||||||
FORCEINLINE constexpr explicit TMoveIterator(IteratorType InValue) : Current(MoveTemp(InValue)) { }
|
FORCEINLINE constexpr explicit TMoveIterator(FIteratorType InValue) : Current(MoveTemp(InValue)) { }
|
||||||
|
|
||||||
template <CInputIterator J> requires (!CSameAs<I, J> && CConstructibleFrom<I, const J&>)
|
template <CInputIterator J> requires (!CSameAs<I, J> && CConstructibleFrom<I, const J&>)
|
||||||
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, I>) TMoveIterator(const TReverseIterator<J>& InValue) : Current(InValue.GetBase()) { }
|
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, I>) TMoveIterator(const TReverseIterator<J>& InValue) : Current(InValue.GetBase()) { }
|
||||||
@ -73,12 +73,12 @@ public:
|
|||||||
|
|
||||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& LHS, const TMoveIterator& RHS) requires (CSizedSentinelFor<I, I>) { return LHS.GetBase() - RHS.GetBase(); }
|
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& LHS, const TMoveIterator& RHS) requires (CSizedSentinelFor<I, I>) { return LHS.GetBase() - RHS.GetBase(); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; }
|
NODISCARD FORCEINLINE constexpr const FIteratorType& GetBase() const& { return Current; }
|
||||||
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); }
|
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { return MoveTemp(Current); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
IteratorType Current;
|
FIteratorType Current;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ class TMoveSentinel
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using SentinelType = S;
|
using FSentinelType = S;
|
||||||
|
|
||||||
FORCEINLINE constexpr TMoveSentinel() = default;
|
FORCEINLINE constexpr TMoveSentinel() = default;
|
||||||
FORCEINLINE constexpr TMoveSentinel(const TMoveSentinel&) = default;
|
FORCEINLINE constexpr TMoveSentinel(const TMoveSentinel&) = default;
|
||||||
@ -109,7 +109,7 @@ public:
|
|||||||
FORCEINLINE constexpr TMoveSentinel& operator=(TMoveSentinel&&) = default;
|
FORCEINLINE constexpr TMoveSentinel& operator=(TMoveSentinel&&) = default;
|
||||||
FORCEINLINE constexpr ~TMoveSentinel() = default;
|
FORCEINLINE constexpr ~TMoveSentinel() = default;
|
||||||
|
|
||||||
FORCEINLINE constexpr explicit TMoveSentinel(SentinelType InValue) : Last(InValue) { }
|
FORCEINLINE constexpr explicit TMoveSentinel(FSentinelType InValue) : Last(InValue) { }
|
||||||
|
|
||||||
template <CSemiregular T> requires (!CSameAs<S, T> && CConstructibleFrom<S, const T&>)
|
template <CSemiregular T> requires (!CSameAs<S, T> && CConstructibleFrom<S, const T&>)
|
||||||
FORCEINLINE constexpr explicit (!CConvertibleTo<const T&, S>) TMoveSentinel(const TMoveSentinel<T>& InValue) : Last(InValue.Last) { }
|
FORCEINLINE constexpr explicit (!CConvertibleTo<const T&, S>) TMoveSentinel(const TMoveSentinel<T>& InValue) : Last(InValue.Last) { }
|
||||||
@ -126,12 +126,12 @@ public:
|
|||||||
template <CInputIterator I> requires (CSizedSentinelFor<S, I>)
|
template <CInputIterator I> requires (CSizedSentinelFor<S, I>)
|
||||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator<I>& Iter, const TMoveSentinel& Sentinel) { return Iter.GetBase() - Sentinel.GetBase(); }
|
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator<I>& Iter, const TMoveSentinel& Sentinel) { return Iter.GetBase() - Sentinel.GetBase(); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr const SentinelType& GetBase() const& { return Last; }
|
NODISCARD FORCEINLINE constexpr const FSentinelType& GetBase() const& { return Last; }
|
||||||
NODISCARD FORCEINLINE constexpr SentinelType GetBase() && { return MoveTemp(Last); }
|
NODISCARD FORCEINLINE constexpr FSentinelType GetBase() && { return MoveTemp(Last); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
SentinelType Last;
|
FSentinelType Last;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ struct IRandomAccessIterator /* : IBidirectionalIterator<T>, ISizedSentinelFor<I
|
|||||||
{
|
{
|
||||||
// ~Begin CBidirectionalIterator.
|
// ~Begin CBidirectionalIterator.
|
||||||
|
|
||||||
using ElementType = TRemoveCVRef<T>;
|
using FElementType = TRemoveCVRef<T>;
|
||||||
|
|
||||||
// ~End CBidirectionalIterator.
|
// ~End CBidirectionalIterator.
|
||||||
|
|
||||||
|
@ -25,9 +25,9 @@ class TReverseIterator final
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using IteratorType = I;
|
using FIteratorType = I;
|
||||||
|
|
||||||
using ElementType = TIteratorElement<I>;
|
using FElementType = TIteratorElement<I>;
|
||||||
|
|
||||||
FORCEINLINE constexpr TReverseIterator() = default;
|
FORCEINLINE constexpr TReverseIterator() = default;
|
||||||
FORCEINLINE constexpr TReverseIterator(const TReverseIterator&) = default;
|
FORCEINLINE constexpr TReverseIterator(const TReverseIterator&) = default;
|
||||||
@ -36,7 +36,7 @@ public:
|
|||||||
FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&&) = default;
|
FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&&) = default;
|
||||||
FORCEINLINE constexpr ~TReverseIterator() = default;
|
FORCEINLINE constexpr ~TReverseIterator() = default;
|
||||||
|
|
||||||
FORCEINLINE constexpr explicit TReverseIterator(IteratorType InValue) : Current(InValue) { }
|
FORCEINLINE constexpr explicit TReverseIterator(FIteratorType InValue) : Current(InValue) { }
|
||||||
|
|
||||||
template <CBidirectionalIterator J> requires (!CSameAs<I, J> && CConstructibleFrom<I, const J&>)
|
template <CBidirectionalIterator J> requires (!CSameAs<I, J> && CConstructibleFrom<I, const J&>)
|
||||||
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, I>) TReverseIterator(const TReverseIterator<J>& InValue) : Current(InValue.GetBase()) { }
|
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, I>) TReverseIterator(const TReverseIterator<J>& InValue) : Current(InValue.GetBase()) { }
|
||||||
@ -50,9 +50,9 @@ public:
|
|||||||
template <CBidirectionalIterator J> requires (CThreeWayComparable<I, J>)
|
template <CBidirectionalIterator J> requires (CThreeWayComparable<I, J>)
|
||||||
NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult<I, J> operator<=>(const TReverseIterator& LHS, const TReverseIterator<J>& RHS) { return RHS.GetBase() <=> LHS.GetBase(); }
|
NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult<I, J> operator<=>(const TReverseIterator& LHS, const TReverseIterator<J>& RHS) { return RHS.GetBase() <=> LHS.GetBase(); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr TIteratorReference<I> operator*() const { IteratorType Temp = GetBase(); return *--Temp; }
|
NODISCARD FORCEINLINE constexpr TIteratorReference<I> operator*() const { FIteratorType Temp = GetBase(); return *--Temp; }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr auto operator->() const requires (requires(const I Iter) { { ToAddress(Iter) } -> CSameAs<TIteratorPointer<I>>; }) { IteratorType Temp = GetBase(); return ToAddress(--Temp); }
|
NODISCARD FORCEINLINE constexpr auto operator->() const requires (requires(const I Iter) { { ToAddress(Iter) } -> CSameAs<TIteratorPointer<I>>; }) { FIteratorType Temp = GetBase(); return ToAddress(--Temp); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr TIteratorReference<I> operator[](ptrdiff Index) const requires (CRandomAccessIterator<I>) { return GetBase()[-Index - 1]; }
|
NODISCARD FORCEINLINE constexpr TIteratorReference<I> operator[](ptrdiff Index) const requires (CRandomAccessIterator<I>) { return GetBase()[-Index - 1]; }
|
||||||
|
|
||||||
@ -72,12 +72,12 @@ public:
|
|||||||
|
|
||||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CSizedSentinelFor<I, I>) { return RHS.GetBase() - LHS.GetBase(); }
|
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CSizedSentinelFor<I, I>) { return RHS.GetBase() - LHS.GetBase(); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; }
|
NODISCARD FORCEINLINE constexpr const FIteratorType& GetBase() const& { return Current; }
|
||||||
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); }
|
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { return MoveTemp(Current); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
IteratorType Current;
|
FIteratorType Current;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,16 +13,16 @@ NAMESPACE_PRIVATE_BEGIN
|
|||||||
template <typename T> using TWithReference = T&;
|
template <typename T> using TWithReference = T&;
|
||||||
|
|
||||||
template <typename I> struct TIteratorElementImpl { };
|
template <typename I> struct TIteratorElementImpl { };
|
||||||
template <typename T> struct TIteratorElementImpl<T*> { using Type = TRemoveCV<T>; };
|
template <typename T> struct TIteratorElementImpl<T*> { using FType = TRemoveCV<T>; };
|
||||||
|
|
||||||
template <typename I> requires (requires { typename I::ElementType; })
|
template <typename I> requires (requires { typename I::FElementType; })
|
||||||
struct TIteratorElementImpl<I> { using Type = typename I::ElementType; };
|
struct TIteratorElementImpl<I> { using FType = typename I::FElementType; };
|
||||||
|
|
||||||
template <typename I> struct TIteratorPointerImpl { };
|
template <typename I> struct TIteratorPointerImpl { };
|
||||||
template <typename T> struct TIteratorPointerImpl<T*> { using Type = T*; };
|
template <typename T> struct TIteratorPointerImpl<T*> { using FType = T*; };
|
||||||
|
|
||||||
template <typename I> requires (requires(I& Iter) { { Iter.operator->() } -> CPointer; })
|
template <typename I> requires (requires(I& Iter) { { Iter.operator->() } -> CPointer; })
|
||||||
struct TIteratorPointerImpl<I> { using Type = decltype(DeclVal<I&>().operator->()); };
|
struct TIteratorPointerImpl<I> { using FType = decltype(DeclVal<I&>().operator->()); };
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
@ -33,10 +33,10 @@ template <typename T>
|
|||||||
concept CDereferenceable = requires(T& A) { { *A } -> CReferenceable; };
|
concept CDereferenceable = requires(T& A) { { *A } -> CReferenceable; };
|
||||||
|
|
||||||
template <typename I>
|
template <typename I>
|
||||||
using TIteratorElement = typename NAMESPACE_PRIVATE::TIteratorElementImpl<TRemoveCVRef<I>>::Type;
|
using TIteratorElement = typename NAMESPACE_PRIVATE::TIteratorElementImpl<TRemoveCVRef<I>>::FType;
|
||||||
|
|
||||||
template <typename I>
|
template <typename I>
|
||||||
using TIteratorPointer = typename NAMESPACE_PRIVATE::TIteratorPointerImpl<TRemoveCVRef<I>>::Type;
|
using TIteratorPointer = typename NAMESPACE_PRIVATE::TIteratorPointerImpl<TRemoveCVRef<I>>::FType;
|
||||||
|
|
||||||
template <CReferenceable I>
|
template <CReferenceable I>
|
||||||
using TIteratorReference = decltype(*DeclVal<I&>());
|
using TIteratorReference = decltype(*DeclVal<I&>());
|
||||||
@ -75,13 +75,13 @@ struct IIndirectlyReadable
|
|||||||
* The element type of the indirectly readable type.
|
* The element type of the indirectly readable type.
|
||||||
* It must be a non-const, non-volatile and non-reference type and can be referenced, i.e. not a void type.
|
* It must be a non-const, non-volatile and non-reference type and can be referenced, i.e. not a void type.
|
||||||
*/
|
*/
|
||||||
using ElementType = TRemoveCVRef<T>;
|
using FElementType = TRemoveCVRef<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indirectly read the element from the indirectly readable type.
|
* Indirectly read the element from the indirectly readable type.
|
||||||
* The return type may not be const ElementType&, this concept only requires that the return type
|
* The return type may not be const FElementType&, this concept only requires that the return type
|
||||||
* and ElementType has some relationship, such as copy constructible to ElementType if the type is copyable.
|
* and FElementType has some relationship, such as copy constructible to FElementType if the type is copyable.
|
||||||
* This means that returning a proxy class castable to ElementType is also valid.
|
* This means that returning a proxy class castable to FElementType is also valid.
|
||||||
* If this is an iterator adaptor, use decltype(auto) to forward the return value.
|
* If this is an iterator adaptor, use decltype(auto) to forward the return value.
|
||||||
*/
|
*/
|
||||||
T operator*() const;
|
T operator*() const;
|
||||||
@ -227,7 +227,7 @@ struct IInputIterator /* : IInputOrOutputIterator, IIndirectlyReadable */
|
|||||||
{
|
{
|
||||||
// ~Begin CIndirectlyReadable.
|
// ~Begin CIndirectlyReadable.
|
||||||
|
|
||||||
using ElementType = TRemoveCVRef<T>;
|
using FElementType = TRemoveCVRef<T>;
|
||||||
|
|
||||||
// ~End CIndirectlyReadable.
|
// ~End CIndirectlyReadable.
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ concept CAllocatableObject = CObject<T> && !CConst<T> && !CVolatile<T> && CDestr
|
|||||||
|
|
||||||
template <typename A, typename T = int>
|
template <typename A, typename T = int>
|
||||||
concept CAllocator = !CSameAs<A, FAllocatorInterface> && CAllocatableObject<T>
|
concept CAllocator = !CSameAs<A, FAllocatorInterface> && CAllocatableObject<T>
|
||||||
&& requires (typename A::template ForElementType<T>& Allocator, T* InPtr, size_t Num, size_t NumAllocated)
|
&& requires (typename A::template TForElementType<T>& Allocator, T* InPtr, size_t Num, size_t NumAllocated)
|
||||||
{
|
{
|
||||||
{ Allocator.Allocate(Num) } -> CSameAs<T*>;
|
{ Allocator.Allocate(Num) } -> CSameAs<T*>;
|
||||||
{ Allocator.Deallocate(InPtr) } -> CSameAs<void>;
|
{ Allocator.Deallocate(InPtr) } -> CSameAs<void>;
|
||||||
@ -47,15 +47,15 @@ struct FAllocatorInterface
|
|||||||
static constexpr bool bSupportsMultipleAllocation = true;
|
static constexpr bool bSupportsMultipleAllocation = true;
|
||||||
|
|
||||||
template <CAllocatableObject T>
|
template <CAllocatableObject T>
|
||||||
class ForElementType /*: private FSingleton*/
|
class TForElementType /*: private FSingleton*/
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ForElementType() = default;
|
TForElementType() = default;
|
||||||
ForElementType(const ForElementType&) = delete;
|
TForElementType(const TForElementType&) = delete;
|
||||||
ForElementType(ForElementType&&) = delete;
|
TForElementType(TForElementType&&) = delete;
|
||||||
ForElementType& operator=(const ForElementType&) = delete;
|
TForElementType& operator=(const TForElementType&) = delete;
|
||||||
ForElementType& operator=(ForElementType&&) = delete;
|
TForElementType& operator=(TForElementType&&) = delete;
|
||||||
|
|
||||||
/** Allocates uninitialized storage. If 'InNum' is zero, return nullptr. */
|
/** Allocates uninitialized storage. If 'InNum' is zero, return nullptr. */
|
||||||
NODISCARD FORCEINLINE T* Allocate(size_t InNum) = delete;
|
NODISCARD FORCEINLINE T* Allocate(size_t InNum) = delete;
|
||||||
@ -110,7 +110,7 @@ struct FAllocatorInterface
|
|||||||
\
|
\
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
PREPROCESSOR_JOIN(T, Name)<typename Allocator::template ForElementType<Type>> Name;
|
PREPROCESSOR_JOIN(T, Name)<typename Allocator::template TForElementType<Type>> Name;
|
||||||
|
|
||||||
/** This is heap allocator that calls Memory::Malloc() directly for memory allocation. */
|
/** This is heap allocator that calls Memory::Malloc() directly for memory allocation. */
|
||||||
struct FHeapAllocator
|
struct FHeapAllocator
|
||||||
@ -118,15 +118,15 @@ struct FHeapAllocator
|
|||||||
static constexpr bool bSupportsMultipleAllocation = true;
|
static constexpr bool bSupportsMultipleAllocation = true;
|
||||||
|
|
||||||
template <CAllocatableObject T>
|
template <CAllocatableObject T>
|
||||||
class ForElementType /*: private FSingleton*/
|
class TForElementType /*: private FSingleton*/
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ForElementType() = default;
|
TForElementType() = default;
|
||||||
ForElementType(const ForElementType&) = delete;
|
TForElementType(const TForElementType&) = delete;
|
||||||
ForElementType(ForElementType&&) = delete;
|
TForElementType(TForElementType&&) = delete;
|
||||||
ForElementType& operator=(const ForElementType&) = delete;
|
TForElementType& operator=(const TForElementType&) = delete;
|
||||||
ForElementType& operator=(ForElementType&&) = delete;
|
TForElementType& operator=(TForElementType&&) = delete;
|
||||||
|
|
||||||
NODISCARD FORCEINLINE T* Allocate(size_t InNum)
|
NODISCARD FORCEINLINE T* Allocate(size_t InNum)
|
||||||
{
|
{
|
||||||
@ -197,15 +197,15 @@ struct TInlineAllocator
|
|||||||
static constexpr bool bSupportsMultipleAllocation = false;
|
static constexpr bool bSupportsMultipleAllocation = false;
|
||||||
|
|
||||||
template <CAllocatableObject T>
|
template <CAllocatableObject T>
|
||||||
class ForElementType /*: private FSingleton*/
|
class TForElementType /*: private FSingleton*/
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ForElementType() = default;
|
TForElementType() = default;
|
||||||
ForElementType(const ForElementType&) = delete;
|
TForElementType(const TForElementType&) = delete;
|
||||||
ForElementType(ForElementType&&) = delete;
|
TForElementType(TForElementType&&) = delete;
|
||||||
ForElementType& operator=(const ForElementType&) = delete;
|
TForElementType& operator=(const TForElementType&) = delete;
|
||||||
ForElementType& operator=(ForElementType&&) = delete;
|
TForElementType& operator=(TForElementType&&) = delete;
|
||||||
|
|
||||||
NODISCARD FORCEINLINE T* Allocate(size_t InNum)
|
NODISCARD FORCEINLINE T* Allocate(size_t InNum)
|
||||||
{
|
{
|
||||||
@ -279,15 +279,15 @@ struct FNullAllocator
|
|||||||
static constexpr bool bSupportsMultipleAllocation = true;
|
static constexpr bool bSupportsMultipleAllocation = true;
|
||||||
|
|
||||||
template <CAllocatableObject T>
|
template <CAllocatableObject T>
|
||||||
class ForElementType /*: private FSingleton*/
|
class TForElementType /*: private FSingleton*/
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ForElementType() = default;
|
TForElementType() = default;
|
||||||
ForElementType(const ForElementType&) = delete;
|
TForElementType(const TForElementType&) = delete;
|
||||||
ForElementType(ForElementType&&) = delete;
|
TForElementType(TForElementType&&) = delete;
|
||||||
ForElementType& operator=(const ForElementType&) = delete;
|
TForElementType& operator=(const TForElementType&) = delete;
|
||||||
ForElementType& operator=(ForElementType&&) = delete;
|
TForElementType& operator=(TForElementType&&) = delete;
|
||||||
|
|
||||||
NODISCARD FORCEINLINE T* Allocate(size_t InNum) { check_no_entry(); return nullptr; }
|
NODISCARD FORCEINLINE T* Allocate(size_t InNum) { check_no_entry(); return nullptr; }
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
|
|||||||
NAMESPACE_PRIVATE_BEGIN
|
NAMESPACE_PRIVATE_BEGIN
|
||||||
|
|
||||||
template <typename RT, typename ST>
|
template <typename RT, typename ST>
|
||||||
using TRawPointer = TConditional<CVoid<RT>, typename TPointerTraits<TRemoveCVRef<ST>>::ElementType*, RT>;
|
using TRawPointer = TConditional<CVoid<RT>, typename TPointerTraits<TRemoveCVRef<ST>>::FElementType*, RT>;
|
||||||
|
|
||||||
template <bool bEnableInput, typename RT, typename ST, typename... Ts>
|
template <bool bEnableInput, typename RT, typename ST, typename... Ts>
|
||||||
class FInOutPtr final : private FSingleton
|
class FInOutPtr final : private FSingleton
|
||||||
@ -57,7 +57,7 @@ NAMESPACE_PRIVATE_END
|
|||||||
template <typename RT = void, typename ST, typename... Ts> requires ((CVoid<RT>) || (CPointer<RT>)
|
template <typename RT = void, typename ST, typename... Ts> requires ((CVoid<RT>) || (CPointer<RT>)
|
||||||
&& (requires(NAMESPACE_PRIVATE::TRawPointer<RT, ST>* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward<Ts>(Args)...); })
|
&& (requires(NAMESPACE_PRIVATE::TRawPointer<RT, ST>* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward<Ts>(Args)...); })
|
||||||
|| (CConstructibleFrom<ST, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, Ts...> && CMoveAssignable<ST>)
|
|| (CConstructibleFrom<ST, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, Ts...> && CMoveAssignable<ST>)
|
||||||
&& requires { typename TPointerTraits<TRemoveCV<ST>>::ElementType; })
|
&& requires { typename TPointerTraits<TRemoveCV<ST>>::FElementType; })
|
||||||
auto OutPtr(ST& InPtr, Ts&&... Args)
|
auto OutPtr(ST& InPtr, Ts&&... Args)
|
||||||
{
|
{
|
||||||
return NAMESPACE_PRIVATE::FInOutPtr<false, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, ST, Ts...>(InPtr, Forward<Ts>(Args)...);
|
return NAMESPACE_PRIVATE::FInOutPtr<false, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, ST, Ts...>(InPtr, Forward<Ts>(Args)...);
|
||||||
@ -67,7 +67,7 @@ template <typename RT = void, typename ST, typename... Ts> requires ((CVoid<RT>)
|
|||||||
&& (requires(NAMESPACE_PRIVATE::TRawPointer<RT, ST>* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward<Ts>(Args)...); })
|
&& (requires(NAMESPACE_PRIVATE::TRawPointer<RT, ST>* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward<Ts>(Args)...); })
|
||||||
|| (CConstructibleFrom<ST, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, Ts...> && CMoveAssignable<ST>)
|
|| (CConstructibleFrom<ST, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, Ts...> && CMoveAssignable<ST>)
|
||||||
&& requires(ST& SPtr) { { SPtr.Release() } -> CConvertibleTo<NAMESPACE_PRIVATE::TRawPointer<RT, ST>>; }
|
&& requires(ST& SPtr) { { SPtr.Release() } -> CConvertibleTo<NAMESPACE_PRIVATE::TRawPointer<RT, ST>>; }
|
||||||
&& requires { typename TPointerTraits<TRemoveCV<ST>>::ElementType; })
|
&& requires { typename TPointerTraits<TRemoveCV<ST>>::FElementType; })
|
||||||
auto InOutPtr(ST& InPtr, Ts&&... Args)
|
auto InOutPtr(ST& InPtr, Ts&&... Args)
|
||||||
{
|
{
|
||||||
return NAMESPACE_PRIVATE::FInOutPtr<true, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, ST, Ts...>(InPtr, Forward<Ts>(Args)...);
|
return NAMESPACE_PRIVATE::FInOutPtr<true, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, ST, Ts...>(InPtr, Forward<Ts>(Args)...);
|
||||||
|
@ -19,10 +19,10 @@ struct TPointerTraits<T*>
|
|||||||
{
|
{
|
||||||
static constexpr bool bIsPointer = true;
|
static constexpr bool bIsPointer = true;
|
||||||
|
|
||||||
using PointerType = T*;
|
using FPointerType = T*;
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
|
|
||||||
static FORCEINLINE constexpr ElementType* ToAddress(PointerType InPtr)
|
static FORCEINLINE constexpr FElementType* ToAddress(FPointerType InPtr)
|
||||||
{
|
{
|
||||||
return InPtr;
|
return InPtr;
|
||||||
}
|
}
|
||||||
@ -34,10 +34,10 @@ struct TPointerTraits<T(*)[]>
|
|||||||
{
|
{
|
||||||
static constexpr bool bIsPointer = true;
|
static constexpr bool bIsPointer = true;
|
||||||
|
|
||||||
using PointerType = T(*)[];
|
using FPointerType = T(*)[];
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
|
|
||||||
static FORCEINLINE constexpr ElementType* ToAddress(PointerType InPtr)
|
static FORCEINLINE constexpr FElementType* ToAddress(FPointerType InPtr)
|
||||||
{
|
{
|
||||||
return InPtr;
|
return InPtr;
|
||||||
}
|
}
|
||||||
@ -50,10 +50,10 @@ struct TPointerTraits<T(*)[]>
|
|||||||
{ \
|
{ \
|
||||||
static constexpr bool bIsPointer = true; \
|
static constexpr bool bIsPointer = true; \
|
||||||
\
|
\
|
||||||
using PointerType = TPtr<T>; \
|
using FPointerType = TPtr<T>; \
|
||||||
using ElementType = TPtr<T>::ElementType; \
|
using FElementType = TPtr<T>::FElementType; \
|
||||||
\
|
\
|
||||||
static FORCEINLINE constexpr ElementType* ToAddress(const PointerType& InPtr) \
|
static FORCEINLINE constexpr FElementType* ToAddress(const FPointerType& InPtr) \
|
||||||
{ \
|
{ \
|
||||||
return InPtr.Get(); \
|
return InPtr.Get(); \
|
||||||
} \
|
} \
|
||||||
|
@ -58,18 +58,18 @@ class alignas(Memory::ConstructiveInterference) FSharedController : private FSin
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using RefCounter = TAtomic<size_t>;
|
using FRefCounter = TAtomic<size_t>;
|
||||||
|
|
||||||
// Ensure that counters are lock-free for performance.
|
// Ensure that counters are lock-free for performance.
|
||||||
static_assert(RefCounter::bIsAlwaysLockFree);
|
static_assert(FRefCounter::bIsAlwaysLockFree);
|
||||||
|
|
||||||
// When this count is zero the object is destroyed.
|
// When this count is zero the object is destroyed.
|
||||||
// This count is the number of TSharedRef and TSharedPtr.
|
// This count is the number of TSharedRef and TSharedPtr.
|
||||||
RefCounter SharedReferenceCount;
|
FRefCounter SharedReferenceCount;
|
||||||
|
|
||||||
// When this count is zero the controller is destroyed.
|
// When this count is zero the controller is destroyed.
|
||||||
// If SharedCounter is not zero this count is one more than the number of TWeakPtr.
|
// If SharedCounter is not zero this count is one more than the number of TWeakPtr.
|
||||||
RefCounter WeakReferenceCount;
|
FRefCounter WeakReferenceCount;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ public:
|
|||||||
virtual void DestroyThis() { delete this; }
|
virtual void DestroyThis() { delete this; }
|
||||||
|
|
||||||
// Get shared reference count, no definite operation order.
|
// Get shared reference count, no definite operation order.
|
||||||
FORCEINLINE RefCounter::ValueType GetSharedReferenceCount()
|
FORCEINLINE FRefCounter::FValueType GetSharedReferenceCount()
|
||||||
{
|
{
|
||||||
// Get the shared reference count as EMemoryOrder::Relaxed,
|
// Get the shared reference count as EMemoryOrder::Relaxed,
|
||||||
// since this count is for reference only and has no guarantees,
|
// since this count is for reference only and has no guarantees,
|
||||||
@ -109,7 +109,7 @@ public:
|
|||||||
// if the shared reference count is zero return false.
|
// if the shared reference count is zero return false.
|
||||||
bool AddSharedReferenceIfUnexpired()
|
bool AddSharedReferenceIfUnexpired()
|
||||||
{
|
{
|
||||||
RefCounter::ValueType OldSharedReferenceCount = GetSharedReferenceCount();
|
FRefCounter::FValueType OldSharedReferenceCount = GetSharedReferenceCount();
|
||||||
|
|
||||||
// We need to make sure we don't increase the reference count from zero to one.
|
// We need to make sure we don't increase the reference count from zero to one.
|
||||||
while (true)
|
while (true)
|
||||||
@ -131,7 +131,7 @@ public:
|
|||||||
// where EMemoryOrder::Release ensures that the side effects of all operations
|
// where EMemoryOrder::Release ensures that the side effects of all operations
|
||||||
// on the shared reference count of all threads are visible to this thread,
|
// on the shared reference count of all threads are visible to this thread,
|
||||||
// preventing the shared reference count from actually going to zero.
|
// preventing the shared reference count from actually going to zero.
|
||||||
RefCounter::ValueType OldSharedReferenceCount = SharedReferenceCount.FetchSub(1, EMemoryOrder::Release);
|
FRefCounter::FValueType OldSharedReferenceCount = SharedReferenceCount.FetchSub(1, EMemoryOrder::Release);
|
||||||
|
|
||||||
// Make sure the shared reference count is not zero before.
|
// Make sure the shared reference count is not zero before.
|
||||||
check(OldSharedReferenceCount != 0);
|
check(OldSharedReferenceCount != 0);
|
||||||
@ -166,7 +166,7 @@ public:
|
|||||||
{
|
{
|
||||||
// The use of EMemoryOrder is the same as in ReleaseSharedReference().
|
// The use of EMemoryOrder is the same as in ReleaseSharedReference().
|
||||||
|
|
||||||
RefCounter::ValueType OldWeakReferenceCount = WeakReferenceCount.FetchSub(1, EMemoryOrder::Release);
|
FRefCounter::FValueType OldWeakReferenceCount = WeakReferenceCount.FetchSub(1, EMemoryOrder::Release);
|
||||||
|
|
||||||
check(OldWeakReferenceCount != 0);
|
check(OldWeakReferenceCount != 0);
|
||||||
|
|
||||||
@ -522,7 +522,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using SharedFromThisType = TSharedFromThis;
|
using FSharedFromThisType = TSharedFromThis;
|
||||||
|
|
||||||
// Here it is updated by the private constructor of TSharedRef or TSharedPtr.
|
// Here it is updated by the private constructor of TSharedRef or TSharedPtr.
|
||||||
mutable TWeakPtr<T> WeakThis;
|
mutable TWeakPtr<T> WeakThis;
|
||||||
@ -539,12 +539,12 @@ class TSharedRef final
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
|
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
using WeakType = TWeakPtr<T>;
|
using FWeakType = TWeakPtr<T>;
|
||||||
|
|
||||||
/** TSharedRef cannot be initialized by nullptr. */
|
/** TSharedRef cannot be initialized by nullptr. */
|
||||||
TSharedRef() = delete;
|
TSharedRef() = delete;
|
||||||
@ -610,18 +610,18 @@ public:
|
|||||||
FORCEINLINE ~TSharedRef() { Controller->ReleaseSharedReference(); }
|
FORCEINLINE ~TSharedRef() { Controller->ReleaseSharedReference(); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return Helper::CopySharedReference(*this, InValue); }
|
FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return FHelper::CopySharedReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
||||||
FORCEINLINE TSharedRef& operator=(const TSharedRef<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
|
FORCEINLINE TSharedRef& operator=(const TSharedRef<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
||||||
FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Compares the pointer values of two TSharedRef. */
|
/** Compares the pointer values of two TSharedRef. */
|
||||||
template <typename U> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
|
template <typename U> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
|
||||||
@ -732,15 +732,15 @@ private:
|
|||||||
{
|
{
|
||||||
check(!((Pointer == nullptr) ^ (Controller == nullptr)));
|
check(!((Pointer == nullptr) ^ (Controller == nullptr)));
|
||||||
|
|
||||||
if constexpr (CClass<T> && !CVolatile<T> && requires { typename T::SharedFromThisType; })
|
if constexpr (CClass<T> && !CVolatile<T> && requires { typename T::FSharedFromThisType; })
|
||||||
{
|
{
|
||||||
using SharedFromThisType = T::SharedFromThisType;
|
using FSharedFromThisType = typename T::FSharedFromThisType;
|
||||||
|
|
||||||
if constexpr (CDerivedFrom<T, SharedFromThisType>)
|
if constexpr (CDerivedFrom<T, FSharedFromThisType>)
|
||||||
{
|
{
|
||||||
if (Pointer != nullptr)
|
if (Pointer != nullptr)
|
||||||
{
|
{
|
||||||
const SharedFromThisType& SharedFromThis = *Pointer;
|
const FSharedFromThisType& SharedFromThis = *Pointer;
|
||||||
checkf(!SharedFromThis.DoesSharedInstanceExist(), TEXT("This object is incorrectly managed by multiple TSharedRef or TSharedPtr."));
|
checkf(!SharedFromThis.DoesSharedInstanceExist(), TEXT("This object is incorrectly managed by multiple TSharedRef or TSharedPtr."));
|
||||||
SharedFromThis.WeakThis = ConstCast<TRemoveCV<T>>(*this);
|
SharedFromThis.WeakThis = ConstCast<TRemoveCV<T>>(*this);
|
||||||
}
|
}
|
||||||
@ -762,12 +762,12 @@ class TSharedRef<T[]> final
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
|
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
using WeakType = TWeakPtr<T>;
|
using FWeakType = TWeakPtr<T>;
|
||||||
|
|
||||||
/** TSharedRef cannot be initialized by nullptr. */
|
/** TSharedRef cannot be initialized by nullptr. */
|
||||||
TSharedRef() = delete;
|
TSharedRef() = delete;
|
||||||
@ -835,18 +835,18 @@ public:
|
|||||||
FORCEINLINE ~TSharedRef() { Controller->ReleaseSharedReference(); }
|
FORCEINLINE ~TSharedRef() { Controller->ReleaseSharedReference(); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return Helper::CopySharedReference(*this, InValue); }
|
FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return FHelper::CopySharedReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
||||||
FORCEINLINE TSharedRef& operator=(const TSharedRef<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
|
FORCEINLINE TSharedRef& operator=(const TSharedRef<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
||||||
FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TSharedRef& operator=(TSharedRef<U>&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Compares the pointer values of two TSharedRef. */
|
/** Compares the pointer values of two TSharedRef. */
|
||||||
template <typename U> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
|
template <typename U> requires (CEqualityComparable<T*, TRemoveExtent<U>*>)
|
||||||
@ -972,12 +972,12 @@ class TSharedPtr final
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
|
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
using WeakType = TWeakPtr<T>;
|
using FWeakType = TWeakPtr<T>;
|
||||||
|
|
||||||
/** Constructs an empty shared pointer. */
|
/** Constructs an empty shared pointer. */
|
||||||
FORCEINLINE constexpr TSharedPtr() : Pointer(nullptr), Controller(nullptr) { }
|
FORCEINLINE constexpr TSharedPtr() : Pointer(nullptr), Controller(nullptr) { }
|
||||||
@ -1073,22 +1073,22 @@ public:
|
|||||||
FORCEINLINE ~TSharedPtr() { if (Controller != nullptr) Controller->ReleaseSharedReference(); }
|
FORCEINLINE ~TSharedPtr() { if (Controller != nullptr) Controller->ReleaseSharedReference(); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return Helper::CopySharedReference(*this, InValue); }
|
FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return FHelper::CopySharedReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
||||||
FORCEINLINE TSharedPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
|
FORCEINLINE TSharedPtr& operator=(const TSharedPtr<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
||||||
FORCEINLINE TSharedPtr& operator=(const TSharedRef<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
|
FORCEINLINE TSharedPtr& operator=(const TSharedRef<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
||||||
FORCEINLINE TSharedPtr& operator=(TSharedPtr<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TSharedPtr& operator=(TSharedPtr<U>&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
template <typename U, typename E> requires (CConvertibleTo<U*, T*> && !CArray<U> && (CDestructible<E> || CLValueReference<E>))
|
template <typename U, typename E> requires (CConvertibleTo<U*, T*> && !CArray<U> && (CDestructible<E> || CLValueReference<E>))
|
||||||
@ -1215,15 +1215,15 @@ private:
|
|||||||
{
|
{
|
||||||
check(!((Pointer == nullptr) ^ (Controller == nullptr)));
|
check(!((Pointer == nullptr) ^ (Controller == nullptr)));
|
||||||
|
|
||||||
if constexpr (CClass<T> && !CVolatile<T> && requires { typename T::SharedFromThisType; })
|
if constexpr (CClass<T> && !CVolatile<T> && requires { typename T::FSharedFromThisType; })
|
||||||
{
|
{
|
||||||
using SharedFromThisType = T::SharedFromThisType;
|
using FSharedFromThisType = typename T::FSharedFromThisType;
|
||||||
|
|
||||||
if constexpr (CDerivedFrom<T, SharedFromThisType>)
|
if constexpr (CDerivedFrom<T, FSharedFromThisType>)
|
||||||
{
|
{
|
||||||
if (Pointer != nullptr)
|
if (Pointer != nullptr)
|
||||||
{
|
{
|
||||||
const SharedFromThisType& SharedFromThis = *Pointer;
|
const FSharedFromThisType& SharedFromThis = *Pointer;
|
||||||
checkf(!SharedFromThis.DoesSharedInstanceExist(), TEXT("This object is incorrectly managed by multiple TSharedRef or TSharedPtr."));
|
checkf(!SharedFromThis.DoesSharedInstanceExist(), TEXT("This object is incorrectly managed by multiple TSharedRef or TSharedPtr."));
|
||||||
SharedFromThis.WeakThis = ConstCast<TRemoveCV<T>>(*this);
|
SharedFromThis.WeakThis = ConstCast<TRemoveCV<T>>(*this);
|
||||||
}
|
}
|
||||||
@ -1245,12 +1245,12 @@ class TSharedPtr<T[]> final
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
|
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
using WeakType = TWeakPtr<T>;
|
using FWeakType = TWeakPtr<T>;
|
||||||
|
|
||||||
/** Constructs an empty shared pointer. */
|
/** Constructs an empty shared pointer. */
|
||||||
FORCEINLINE constexpr TSharedPtr() : Pointer(nullptr), Controller(nullptr) { }
|
FORCEINLINE constexpr TSharedPtr() : Pointer(nullptr), Controller(nullptr) { }
|
||||||
@ -1348,22 +1348,22 @@ public:
|
|||||||
FORCEINLINE ~TSharedPtr() { if (Controller != nullptr) Controller->ReleaseSharedReference(); }
|
FORCEINLINE ~TSharedPtr() { if (Controller != nullptr) Controller->ReleaseSharedReference(); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return Helper::CopySharedReference(*this, InValue); }
|
FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return FHelper::CopySharedReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
||||||
FORCEINLINE TSharedPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
|
FORCEINLINE TSharedPtr& operator=(const TSharedPtr<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
||||||
FORCEINLINE TSharedPtr& operator=(const TSharedRef<U>& InValue) { return Helper::CopySharedReference(*this, InValue); }
|
FORCEINLINE TSharedPtr& operator=(const TSharedRef<U>& InValue) { return FHelper::CopySharedReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
||||||
FORCEINLINE TSharedPtr& operator=(TSharedPtr<U>&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TSharedPtr& operator=(TSharedPtr<U>&& InValue) { return FHelper::MoveSharedReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
template <typename U, typename E> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U> && (CDestructible<E> || CLValueReference<E>))
|
template <typename U, typename E> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U> && (CDestructible<E> || CLValueReference<E>))
|
||||||
@ -1505,11 +1505,11 @@ class TWeakPtr final
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
|
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
|
|
||||||
/** Constructs an empty TWeakPtr */
|
/** Constructs an empty TWeakPtr */
|
||||||
FORCEINLINE constexpr TWeakPtr() : Pointer(nullptr), Controller(nullptr) { }
|
FORCEINLINE constexpr TWeakPtr() : Pointer(nullptr), Controller(nullptr) { }
|
||||||
@ -1564,26 +1564,26 @@ public:
|
|||||||
FORCEINLINE ~TWeakPtr() { if (Controller != nullptr) Controller->ReleaseWeakReference(); }
|
FORCEINLINE ~TWeakPtr() { if (Controller != nullptr) Controller->ReleaseWeakReference(); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return Helper::CopyWeakReference(*this, InValue); }
|
FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
||||||
FORCEINLINE TWeakPtr& operator=(const TWeakPtr<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
|
FORCEINLINE TWeakPtr& operator=(const TWeakPtr<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return FHelper::MoveWeakReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Replaces the managed object with the one managed by 'InValue'. */
|
/** Replaces the managed object with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
||||||
FORCEINLINE TWeakPtr& operator=(TWeakPtr<U>&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TWeakPtr& operator=(TWeakPtr<U>&& InValue) { return FHelper::MoveWeakReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Assignment operator sets this weak pointer from a shared reference. */
|
/** Assignment operator sets this weak pointer from a shared reference. */
|
||||||
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
||||||
FORCEINLINE TWeakPtr& operator=(const TSharedRef<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
|
FORCEINLINE TWeakPtr& operator=(const TSharedRef<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
|
||||||
|
|
||||||
/** Assignment operator sets this weak pointer from a shared pointer. */
|
/** Assignment operator sets this weak pointer from a shared pointer. */
|
||||||
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
|
||||||
FORCEINLINE TWeakPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
|
FORCEINLINE TWeakPtr& operator=(const TSharedPtr<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
|
||||||
|
|
||||||
/** Effectively the same as calling Reset(). */
|
/** Effectively the same as calling Reset(). */
|
||||||
FORCEINLINE TWeakPtr& operator=(nullptr_t) { Reset(); return *this; }
|
FORCEINLINE TWeakPtr& operator=(nullptr_t) { Reset(); return *this; }
|
||||||
@ -1639,11 +1639,11 @@ class TWeakPtr<T[]> final
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Helper = NAMESPACE_PRIVATE::FSharedHelper;
|
using FHelper = NAMESPACE_PRIVATE::FSharedHelper;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
|
|
||||||
/** Constructs an empty TWeakPtr */
|
/** Constructs an empty TWeakPtr */
|
||||||
FORCEINLINE constexpr TWeakPtr() : Pointer(nullptr), Controller(nullptr) { }
|
FORCEINLINE constexpr TWeakPtr() : Pointer(nullptr), Controller(nullptr) { }
|
||||||
@ -1698,26 +1698,26 @@ public:
|
|||||||
FORCEINLINE ~TWeakPtr() { if (Controller != nullptr) Controller->ReleaseWeakReference(); }
|
FORCEINLINE ~TWeakPtr() { if (Controller != nullptr) Controller->ReleaseWeakReference(); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return Helper::CopyWeakReference(*this, InValue); }
|
FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
||||||
FORCEINLINE TWeakPtr& operator=(const TWeakPtr<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
|
FORCEINLINE TWeakPtr& operator=(const TWeakPtr<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return FHelper::MoveWeakReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Replaces the managed array with the one managed by 'InValue'. */
|
/** Replaces the managed array with the one managed by 'InValue'. */
|
||||||
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
||||||
FORCEINLINE TWeakPtr& operator=(TWeakPtr<U>&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); }
|
FORCEINLINE TWeakPtr& operator=(TWeakPtr<U>&& InValue) { return FHelper::MoveWeakReference(*this, MoveTemp(InValue)); }
|
||||||
|
|
||||||
/** Assignment operator sets this weak pointer from a shared reference. */
|
/** Assignment operator sets this weak pointer from a shared reference. */
|
||||||
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
||||||
FORCEINLINE TWeakPtr& operator=(const TSharedRef<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
|
FORCEINLINE TWeakPtr& operator=(const TSharedRef<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
|
||||||
|
|
||||||
/** Assignment operator sets this weak pointer from a shared pointer. */
|
/** Assignment operator sets this weak pointer from a shared pointer. */
|
||||||
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
|
||||||
FORCEINLINE TWeakPtr& operator=(const TSharedPtr<U>& InValue) { return Helper::CopyWeakReference(*this, InValue); }
|
FORCEINLINE TWeakPtr& operator=(const TSharedPtr<U>& InValue) { return FHelper::CopyWeakReference(*this, InValue); }
|
||||||
|
|
||||||
/** Effectively the same as calling Reset(). */
|
/** Effectively the same as calling Reset(). */
|
||||||
FORCEINLINE TWeakPtr& operator=(nullptr_t) { Reset(); return *this; }
|
FORCEINLINE TWeakPtr& operator=(nullptr_t) { Reset(); return *this; }
|
||||||
|
@ -179,8 +179,8 @@ class TUniqueRef final : private FSingleton
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
using DeleterType = E;
|
using FDeleterType = E;
|
||||||
|
|
||||||
/** TUniqueRef cannot be initialized by nullptr. */
|
/** TUniqueRef cannot be initialized by nullptr. */
|
||||||
TUniqueRef() = delete;
|
TUniqueRef() = delete;
|
||||||
@ -308,8 +308,8 @@ class TUniqueRef<T[], E> final : private FSingleton
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
using DeleterType = E;
|
using FDeleterType = E;
|
||||||
|
|
||||||
/** TUniqueRef cannot be initialized by nullptr. */
|
/** TUniqueRef cannot be initialized by nullptr. */
|
||||||
TUniqueRef() = delete;
|
TUniqueRef() = delete;
|
||||||
@ -439,8 +439,8 @@ class TUniquePtr final : private FNoncopyable
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
using DeleterType = E;
|
using FDeleterType = E;
|
||||||
|
|
||||||
/** Constructs a TUniquePtr that owns nothing. Value-initializes the stored pointer and the stored deleter. */
|
/** Constructs a TUniquePtr that owns nothing. Value-initializes the stored pointer and the stored deleter. */
|
||||||
FORCEINLINE constexpr TUniquePtr() requires(CDefaultConstructible<E> && !CPointer<E>) : Storage(nullptr) { }
|
FORCEINLINE constexpr TUniquePtr() requires(CDefaultConstructible<E> && !CPointer<E>) : Storage(nullptr) { }
|
||||||
@ -585,8 +585,8 @@ class TUniquePtr<T[], E> final : private FNoncopyable
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
using DeleterType = E;
|
using FDeleterType = E;
|
||||||
|
|
||||||
/** Constructs a TUniquePtr that owns nothing. Value-initializes the stored pointer and the stored deleter. */
|
/** Constructs a TUniquePtr that owns nothing. Value-initializes the stored pointer and the stored deleter. */
|
||||||
FORCEINLINE constexpr TUniquePtr() requires(CDefaultConstructible<E> && !CPointer<E>) : Storage(nullptr) { }
|
FORCEINLINE constexpr TUniquePtr() requires(CDefaultConstructible<E> && !CPointer<E>) : Storage(nullptr) { }
|
||||||
|
@ -42,6 +42,8 @@ NAMESPACE_PRIVATE_END
|
|||||||
# define DO_CHECK 0
|
# define DO_CHECK 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// ReSharper disable CppInconsistentNaming
|
||||||
|
|
||||||
#define always_check(InExpr) RS_CHECK_IMPL(InExpr)
|
#define always_check(InExpr) RS_CHECK_IMPL(InExpr)
|
||||||
#define always_checkf(InExpr, InFormat, ...) RS_CHECK_F_IMPL(InExpr, InFormat, ##__VA_ARGS__)
|
#define always_checkf(InExpr, InFormat, ...) RS_CHECK_F_IMPL(InExpr, InFormat, ##__VA_ARGS__)
|
||||||
#define always_check_no_entry() always_checkf(false, "Enclosing block should never be called.")
|
#define always_check_no_entry() always_checkf(false, "Enclosing block should never be called.")
|
||||||
@ -77,6 +79,8 @@ NAMESPACE_PRIVATE_END
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// ReSharper restore CppInconsistentNaming
|
||||||
|
|
||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
NAMESPACE_MODULE_END(Redcraft)
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
NAMESPACE_REDCRAFT_END
|
NAMESPACE_REDCRAFT_END
|
||||||
|
@ -12,17 +12,21 @@ NAMESPACE_MODULE_BEGIN(Utility)
|
|||||||
|
|
||||||
// The result of the three-way comparison operator is the built-in type of the compiler, which is directly introduced here
|
// The result of the three-way comparison operator is the built-in type of the compiler, which is directly introduced here
|
||||||
|
|
||||||
typedef NAMESPACE_STD::partial_ordering partial_ordering;
|
// ReSharper disable CppInconsistentNaming
|
||||||
typedef NAMESPACE_STD::weak_ordering weak_ordering;
|
|
||||||
typedef NAMESPACE_STD::strong_ordering strong_ordering;
|
using partial_ordering = NAMESPACE_STD::partial_ordering;
|
||||||
|
using weak_ordering = NAMESPACE_STD::weak_ordering;
|
||||||
|
using strong_ordering = NAMESPACE_STD::strong_ordering;
|
||||||
|
|
||||||
|
// ReSharper restore CppInconsistentNaming
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_BEGIN
|
NAMESPACE_PRIVATE_BEGIN
|
||||||
|
|
||||||
template<int32> struct TCommonComparisonCategoryBasic { };
|
template<int32> struct TCommonComparisonCategoryBasic { };
|
||||||
template<> struct TCommonComparisonCategoryBasic<0> { using Type = strong_ordering; };
|
template<> struct TCommonComparisonCategoryBasic<0> { using FType = strong_ordering; };
|
||||||
template<> struct TCommonComparisonCategoryBasic<2> { using Type = partial_ordering; };
|
template<> struct TCommonComparisonCategoryBasic<2> { using FType = partial_ordering; };
|
||||||
template<> struct TCommonComparisonCategoryBasic<4> { using Type = weak_ordering; };
|
template<> struct TCommonComparisonCategoryBasic<4> { using FType = weak_ordering; };
|
||||||
template<> struct TCommonComparisonCategoryBasic<6> { using Type = partial_ordering; };
|
template<> struct TCommonComparisonCategoryBasic<6> { using FType = partial_ordering; };
|
||||||
|
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
struct TCommonComparisonCategoryImpl
|
struct TCommonComparisonCategoryImpl
|
||||||
@ -38,7 +42,7 @@ struct TCommonComparisonCategoryImpl
|
|||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
using TCommonComparisonCategory = typename NAMESPACE_PRIVATE::TCommonComparisonCategoryImpl<Ts...>::Type;
|
using TCommonComparisonCategory = typename NAMESPACE_PRIVATE::TCommonComparisonCategoryImpl<Ts...>::FType;
|
||||||
|
|
||||||
template <typename T, typename OrderingType>
|
template <typename T, typename OrderingType>
|
||||||
concept CThreeWayComparesAs = CSameAs<TCommonComparisonCategory<T, OrderingType>, OrderingType>;
|
concept CThreeWayComparesAs = CSameAs<TCommonComparisonCategory<T, OrderingType>, OrderingType>;
|
||||||
|
@ -17,7 +17,7 @@ class TConstantIterator final
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TRemoveCV<T>;
|
using FElementType = TRemoveCV<T>;
|
||||||
|
|
||||||
FORCEINLINE constexpr TConstantIterator() = default;
|
FORCEINLINE constexpr TConstantIterator() = default;
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ class TConstantIterator<T&> final
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TRemoveCV<T>;
|
using FElementType = TRemoveCV<T>;
|
||||||
|
|
||||||
FORCEINLINE constexpr TConstantIterator() = default;
|
FORCEINLINE constexpr TConstantIterator() = default;
|
||||||
|
|
||||||
@ -115,14 +115,14 @@ class TCountedIterator<TConstantIterator<T>> final
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using IteratorType = TConstantIterator<T>;
|
using FIteratorType = TConstantIterator<T>;
|
||||||
|
|
||||||
using ElementType = typename TConstantIterator<T>::ElementType;
|
using FElementType = typename TConstantIterator<T>::FElementType;
|
||||||
|
|
||||||
# if DO_CHECK
|
# if DO_CHECK
|
||||||
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<IteratorType>) : Length(1), MaxLength(0) { }
|
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<FIteratorType>) : Length(1), MaxLength(0) { }
|
||||||
# else
|
# else
|
||||||
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<IteratorType>) = default;
|
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<FIteratorType>) = default;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
FORCEINLINE constexpr TCountedIterator(const TCountedIterator&) = default;
|
FORCEINLINE constexpr TCountedIterator(const TCountedIterator&) = default;
|
||||||
@ -132,25 +132,25 @@ public:
|
|||||||
|
|
||||||
FORCEINLINE constexpr ~TCountedIterator() = default;
|
FORCEINLINE constexpr ~TCountedIterator() = default;
|
||||||
|
|
||||||
template <typename U = IteratorType> requires (!CSameAs<TCountedIterator, TRemoveCVRef<U>> && CConstructibleFrom<IteratorType, U>)
|
template <typename U = FIteratorType> requires (!CSameAs<TCountedIterator, TRemoveCVRef<U>> && CConstructibleFrom<FIteratorType, U>)
|
||||||
FORCEINLINE constexpr explicit TCountedIterator(U&& InValue, ptrdiff N) : Current(Forward<U>(InValue)), Length(N) { check_code({ MaxLength = N; }); }
|
FORCEINLINE constexpr explicit TCountedIterator(U&& InValue, ptrdiff N) : Current(Forward<U>(InValue)), Length(N) { check_code({ MaxLength = N; }); }
|
||||||
|
|
||||||
template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConstructibleFrom<IteratorType, const J&>)
|
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConstructibleFrom<FIteratorType, const J&>)
|
||||||
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, IteratorType>) TCountedIterator(const TCountedIterator<J>& InValue) : Current(InValue.Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
|
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, FIteratorType>) TCountedIterator(const TCountedIterator<J>& InValue) : Current(InValue.Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
|
||||||
|
|
||||||
template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConstructibleFrom<IteratorType, J>)
|
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConstructibleFrom<FIteratorType, J>)
|
||||||
FORCEINLINE constexpr explicit (!CConvertibleTo<J&&, IteratorType>) TCountedIterator(TCountedIterator<J>&& InValue) : Current(MoveTemp(InValue).Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
|
FORCEINLINE constexpr explicit (!CConvertibleTo<J&&, FIteratorType>) TCountedIterator(TCountedIterator<J>&& InValue) : Current(MoveTemp(InValue).Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
|
||||||
|
|
||||||
template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConvertibleTo<const J&, IteratorType> && CAssignableFrom<IteratorType&, const J&>)
|
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConvertibleTo<const J&, FIteratorType> && CAssignableFrom<FIteratorType&, const J&>)
|
||||||
FORCEINLINE constexpr TCountedIterator& operator=(const TCountedIterator<J>& InValue) { Current = InValue.Current; Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; }
|
FORCEINLINE constexpr TCountedIterator& operator=(const TCountedIterator<J>& InValue) { Current = InValue.Current; Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; }
|
||||||
|
|
||||||
template <CInputOrOutputIterator J> requires (!CSameAs<IteratorType, J> && CConvertibleTo<J&&, IteratorType> && CAssignableFrom<IteratorType&, J&&>)
|
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConvertibleTo<J&&, FIteratorType> && CAssignableFrom<FIteratorType&, J&&>)
|
||||||
FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator<J>&& InValue) { Current = MoveTemp(InValue).Current; Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; }
|
FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator<J>&& InValue) { Current = MoveTemp(InValue).Current; Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; }
|
||||||
|
|
||||||
template <CCommonType<IteratorType> J>
|
template <CCommonType<FIteratorType> J>
|
||||||
NODISCARD friend FORCEINLINE constexpr bool operator==(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { return LHS.Length == RHS.Length; }
|
NODISCARD friend FORCEINLINE constexpr bool operator==(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { return LHS.Length == RHS.Length; }
|
||||||
|
|
||||||
template <CCommonType<IteratorType> J>
|
template <CCommonType<FIteratorType> J>
|
||||||
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { return LHS.Length <=> RHS.Length; }
|
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { return LHS.Length <=> RHS.Length; }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr bool operator==(FDefaultSentinel) const& { return Length == static_cast<ptrdiff>(0); }
|
NODISCARD FORCEINLINE constexpr bool operator==(FDefaultSentinel) const& { return Length == static_cast<ptrdiff>(0); }
|
||||||
@ -176,19 +176,19 @@ public:
|
|||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr TCountedIterator operator-(ptrdiff Offset) const { TCountedIterator Temp = *this; Temp -= Offset; return Temp; }
|
NODISCARD FORCEINLINE constexpr TCountedIterator operator-(ptrdiff Offset) const { TCountedIterator Temp = *this; Temp -= Offset; return Temp; }
|
||||||
|
|
||||||
template <CCommonType<IteratorType> J>
|
template <CCommonType<FIteratorType> J>
|
||||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Length - RHS.Length; }
|
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Length - RHS.Length; }
|
||||||
|
|
||||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { LHS.CheckThis(); return -LHS.Num(); }
|
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { LHS.CheckThis(); return -LHS.Num(); }
|
||||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { RHS.CheckThis(); return RHS.Num(); }
|
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { RHS.CheckThis(); return RHS.Num(); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { CheckThis(); return Current; }
|
NODISCARD FORCEINLINE constexpr const FIteratorType& GetBase() const& { CheckThis(); return Current; }
|
||||||
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { CheckThis(); return MoveTemp(Current); }
|
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { CheckThis(); return MoveTemp(Current); }
|
||||||
NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; }
|
NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
IteratorType Current;
|
FIteratorType Current;
|
||||||
ptrdiff Length;
|
ptrdiff Length;
|
||||||
|
|
||||||
# if DO_CHECK
|
# if DO_CHECK
|
||||||
|
@ -9,6 +9,8 @@ NAMESPACE_REDCRAFT_BEGIN
|
|||||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||||
NAMESPACE_MODULE_BEGIN(Utility)
|
NAMESPACE_MODULE_BEGIN(Utility)
|
||||||
|
|
||||||
|
// ReSharper disable CppInconsistentNaming
|
||||||
|
|
||||||
#define NORETURN [[noreturn]]
|
#define NORETURN [[noreturn]]
|
||||||
#define CARRIES_DEPENDENCY [[carries_dependency]]
|
#define CARRIES_DEPENDENCY [[carries_dependency]]
|
||||||
#define DEPRECATED(Message) [[deprecated(Message)]]
|
#define DEPRECATED(Message) [[deprecated(Message)]]
|
||||||
@ -42,6 +44,8 @@ using type_info = NAMESPACE_STD::type_info;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
using initializer_list = NAMESPACE_STD::initializer_list<T>;
|
using initializer_list = NAMESPACE_STD::initializer_list<T>;
|
||||||
|
|
||||||
|
// ReSharper restore CppInconsistentNaming
|
||||||
|
|
||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
NAMESPACE_MODULE_END(Redcraft)
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
NAMESPACE_REDCRAFT_END
|
NAMESPACE_REDCRAFT_END
|
||||||
|
@ -14,6 +14,8 @@ NAMESPACE_REDCRAFT_BEGIN
|
|||||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||||
NAMESPACE_MODULE_BEGIN(Utility)
|
NAMESPACE_MODULE_BEGIN(Utility)
|
||||||
|
|
||||||
|
// ReSharper disable CppInconsistentNaming
|
||||||
|
|
||||||
// Platform information macro
|
// Platform information macro
|
||||||
|
|
||||||
#ifndef PLATFORM_NAME
|
#ifndef PLATFORM_NAME
|
||||||
@ -527,6 +529,8 @@ NAMESPACE_PRIVATE_END
|
|||||||
#define U32TEXT(X) U32TEXT_PASTE(X)
|
#define U32TEXT(X) U32TEXT_PASTE(X)
|
||||||
#define UNICODETEXT(X) U32TEXT_PASTE(X)
|
#define UNICODETEXT(X) U32TEXT_PASTE(X)
|
||||||
|
|
||||||
|
// ReSharper restore CppInconsistentNaming
|
||||||
|
|
||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
NAMESPACE_MODULE_END(Redcraft)
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
NAMESPACE_REDCRAFT_END
|
NAMESPACE_REDCRAFT_END
|
||||||
|
@ -444,83 +444,83 @@ RESOLVE_ARITHMETIC_AMBIGUITY_2_ARGS(CArithmetic, IsNearlyZero)
|
|||||||
template <CFloatingPoint T>
|
template <CFloatingPoint T>
|
||||||
NODISCARD FORCEINLINE constexpr bool IsInfinity(T A)
|
NODISCARD FORCEINLINE constexpr bool IsInfinity(T A)
|
||||||
{
|
{
|
||||||
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
||||||
|
|
||||||
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
|
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
|
||||||
|
|
||||||
return (IntegralValue & Traits::ExponentMask) == Traits::ExponentMask && (IntegralValue & Traits::MantissaMask) == 0;
|
return (IntegralValue & FTraits::ExponentMask) == FTraits::ExponentMask && (IntegralValue & FTraits::MantissaMask) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the given value is NaN, false otherwise. */
|
/** @return true if the given value is NaN, false otherwise. */
|
||||||
template <CFloatingPoint T>
|
template <CFloatingPoint T>
|
||||||
NODISCARD FORCEINLINE constexpr bool IsNaN(T A)
|
NODISCARD FORCEINLINE constexpr bool IsNaN(T A)
|
||||||
{
|
{
|
||||||
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
||||||
|
|
||||||
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
|
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
|
||||||
|
|
||||||
return (IntegralValue & Traits::ExponentMask) == Traits::ExponentMask && (IntegralValue & Traits::MantissaMask) != 0;
|
return (IntegralValue & FTraits::ExponentMask) == FTraits::ExponentMask && (IntegralValue & FTraits::MantissaMask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the given value is normal, false otherwise. */
|
/** @return true if the given value is normal, false otherwise. */
|
||||||
template <CFloatingPoint T>
|
template <CFloatingPoint T>
|
||||||
NODISCARD FORCEINLINE constexpr bool IsNormal(T A)
|
NODISCARD FORCEINLINE constexpr bool IsNormal(T A)
|
||||||
{
|
{
|
||||||
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
||||||
|
|
||||||
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
|
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
|
||||||
|
|
||||||
return (IntegralValue & Traits::ExponentMask) != 0 && (IntegralValue & Traits::ExponentMask) != Traits::ExponentMask;
|
return (IntegralValue & FTraits::ExponentMask) != 0 && (IntegralValue & FTraits::ExponentMask) != FTraits::ExponentMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the given value is subnormal, false otherwise. */
|
/** @return true if the given value is subnormal, false otherwise. */
|
||||||
template <CFloatingPoint T>
|
template <CFloatingPoint T>
|
||||||
NODISCARD FORCEINLINE constexpr bool IsDenorm(T A)
|
NODISCARD FORCEINLINE constexpr bool IsDenorm(T A)
|
||||||
{
|
{
|
||||||
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
||||||
|
|
||||||
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
|
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
|
||||||
|
|
||||||
return (IntegralValue & Traits::ExponentMask) == 0 && (IntegralValue & Traits::MantissaMask) != 0;
|
return (IntegralValue & FTraits::ExponentMask) == 0 && (IntegralValue & FTraits::MantissaMask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the given value is negative, even -0.0, false otherwise. */
|
/** @return true if the given value is negative, even -0.0, false otherwise. */
|
||||||
template <CFloatingPoint T>
|
template <CFloatingPoint T>
|
||||||
NODISCARD FORCEINLINE constexpr bool IsNegative(T A)
|
NODISCARD FORCEINLINE constexpr bool IsNegative(T A)
|
||||||
{
|
{
|
||||||
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
||||||
|
|
||||||
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
|
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
|
||||||
|
|
||||||
return (IntegralValue & Traits::SignMask) >> Traits::SignShift;
|
return (IntegralValue & FTraits::SignMask) >> FTraits::SignShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The exponent of the given value. */
|
/** @return The exponent of the given value. */
|
||||||
template <CFloatingPoint T>
|
template <CFloatingPoint T>
|
||||||
NODISCARD FORCEINLINE constexpr uint Exponent(T A)
|
NODISCARD FORCEINLINE constexpr uint Exponent(T A)
|
||||||
{
|
{
|
||||||
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
||||||
|
|
||||||
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
|
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
|
||||||
|
|
||||||
return ((IntegralValue & Traits::ExponentMask) >> Traits::ExponentShift) - Traits::ExponentBias;
|
return ((IntegralValue & FTraits::ExponentMask) >> FTraits::ExponentShift) - FTraits::ExponentBias;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The NaN value with the given payload. */
|
/** @return The NaN value with the given payload. */
|
||||||
template <CFloatingPoint T, CUnsignedIntegral U>
|
template <CFloatingPoint T, CUnsignedIntegral U>
|
||||||
NODISCARD FORCEINLINE constexpr T NaN(U Payload)
|
NODISCARD FORCEINLINE constexpr T NaN(U Payload)
|
||||||
{
|
{
|
||||||
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
||||||
|
|
||||||
checkf(Payload != 0, TEXT("Illegal payload. It must not be zero."));
|
checkf(Payload != 0, TEXT("Illegal payload. It must not be zero."));
|
||||||
|
|
||||||
checkf(Payload < (static_cast<typename Traits::FIntegralT>(1) << Traits::MantissaBits), TEXT("Illegal payload. It must be less than 2^MantissaBits."));
|
checkf(Payload < (static_cast<typename FTraits::FIntegralT>(1) << FTraits::MantissaBits), TEXT("Illegal payload. It must be less than 2^MantissaBits."));
|
||||||
|
|
||||||
if (Payload == 0) return TNumericLimits<T>::QuietNaN();
|
if (Payload == 0) return TNumericLimits<T>::QuietNaN();
|
||||||
|
|
||||||
typename Traits::FIntegralT ValidPayload = Payload & Traits::MantissaMask;
|
typename FTraits::FIntegralT ValidPayload = Payload & FTraits::MantissaMask;
|
||||||
|
|
||||||
return Math::BitCast<T>(ValidPayload | Traits::ExponentMask);
|
return Math::BitCast<T>(ValidPayload | FTraits::ExponentMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The NaN value with the given payload. */
|
/** @return The NaN value with the given payload. */
|
||||||
@ -536,11 +536,11 @@ NODISCARD FORCEINLINE constexpr T NaN(U Payload)
|
|||||||
template <CFloatingPoint T>
|
template <CFloatingPoint T>
|
||||||
NODISCARD FORCEINLINE constexpr auto NaNPayload(T A)
|
NODISCARD FORCEINLINE constexpr auto NaNPayload(T A)
|
||||||
{
|
{
|
||||||
using Traits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
using FTraits = NAMESPACE_PRIVATE::TFloatingTypeTraits<T>;
|
||||||
|
|
||||||
auto IntegralValue = Math::BitCast<typename Traits::FIntegralT>(A);
|
auto IntegralValue = Math::BitCast<typename FTraits::FIntegralT>(A);
|
||||||
|
|
||||||
return IntegralValue & Traits::MantissaMask;
|
return IntegralValue & FTraits::MantissaMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The NaN payload of the given value. */
|
/** @return The NaN payload of the given value. */
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "CoreTypes.h"
|
#include "CoreTypes.h"
|
||||||
#include "Range/View.h"
|
#include "Range/View.h"
|
||||||
|
#include "Range/Pipe.h"
|
||||||
#include "Range/Utility.h"
|
#include "Range/Utility.h"
|
||||||
#include "Templates/Utility.h"
|
#include "Templates/Utility.h"
|
||||||
#include "TypeTraits/TypeTraits.h"
|
#include "TypeTraits/TypeTraits.h"
|
||||||
@ -148,6 +149,15 @@ NODISCARD FORCEINLINE constexpr auto All(R&& InRange)
|
|||||||
else return TOwningView(Forward<R>(InRange));
|
else return TOwningView(Forward<R>(InRange));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Creates A view adapter that includes all elements of a range. */
|
||||||
|
NODISCARD FORCEINLINE constexpr auto All()
|
||||||
|
{
|
||||||
|
return TAdaptorClosure([]<CViewableRange R> requires (requires { All(DeclVal<R&&>()); }) (R && Base)
|
||||||
|
{
|
||||||
|
return All(Forward<R>(Base));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** A view adapter that includes all elements of a range. */
|
/** A view adapter that includes all elements of a range. */
|
||||||
template <CViewableRange R>
|
template <CViewableRange R>
|
||||||
using TAllView = decltype(Range::All(DeclVal<R>()));
|
using TAllView = decltype(Range::All(DeclVal<R>()));
|
||||||
|
@ -19,15 +19,15 @@ class TEmptyView : public IBasicViewInterface<TEmptyView<T>>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
using Reference = T&;
|
using FReference = T&;
|
||||||
using Iterator = T*;
|
using FIterator = T*;
|
||||||
using Sentinel = T*;
|
using FSentinel = T*;
|
||||||
|
|
||||||
FORCEINLINE constexpr TEmptyView() = default;
|
FORCEINLINE constexpr TEmptyView() = default;
|
||||||
|
|
||||||
NODISCARD static FORCEINLINE constexpr Iterator Begin() { return nullptr; }
|
NODISCARD static FORCEINLINE constexpr FIterator Begin() { return nullptr; }
|
||||||
NODISCARD static FORCEINLINE constexpr Sentinel End() { return nullptr; }
|
NODISCARD static FORCEINLINE constexpr FSentinel End() { return nullptr; }
|
||||||
NODISCARD static FORCEINLINE constexpr T* GetData() { return nullptr; }
|
NODISCARD static FORCEINLINE constexpr T* GetData() { return nullptr; }
|
||||||
NODISCARD static FORCEINLINE constexpr size_t Num() { return 0; }
|
NODISCARD static FORCEINLINE constexpr size_t Num() { return 0; }
|
||||||
NODISCARD static FORCEINLINE constexpr bool IsEmpty() { return true; }
|
NODISCARD static FORCEINLINE constexpr bool IsEmpty() { return true; }
|
||||||
@ -52,16 +52,16 @@ class TSingleView : public IBasicViewInterface<TSingleView<T>>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
|
|
||||||
using Reference = T&;
|
using FReference = T&;
|
||||||
using ConstReference = const T&;
|
using FConstReference = const T&;
|
||||||
|
|
||||||
using Iterator = T*;
|
using FIterator = T*;
|
||||||
using ConstIterator = const T*;
|
using FConstIterator = const T*;
|
||||||
|
|
||||||
using Sentinel = T*;
|
using FSentinel = T*;
|
||||||
using ConstSentinel = const T*;
|
using FConstSentinel = const T*;
|
||||||
|
|
||||||
FORCEINLINE constexpr TSingleView() requires (CDefaultConstructible<T>) = default;
|
FORCEINLINE constexpr TSingleView() requires (CDefaultConstructible<T>) = default;
|
||||||
|
|
||||||
@ -72,10 +72,10 @@ public:
|
|||||||
template <typename... Ts> requires (CConstructibleFrom<T, Ts...>)
|
template <typename... Ts> requires (CConstructibleFrom<T, Ts...>)
|
||||||
FORCEINLINE constexpr explicit TSingleView(FInPlace, Ts&&... Args) : Value(Forward<Ts>(Args)...) { }
|
FORCEINLINE constexpr explicit TSingleView(FInPlace, Ts&&... Args) : Value(Forward<Ts>(Args)...) { }
|
||||||
|
|
||||||
FORCEINLINE constexpr Iterator Begin() { return GetData(); }
|
FORCEINLINE constexpr FIterator Begin() { return GetData(); }
|
||||||
FORCEINLINE constexpr ConstIterator Begin() const { return GetData(); }
|
FORCEINLINE constexpr FConstIterator Begin() const { return GetData(); }
|
||||||
FORCEINLINE constexpr Sentinel End() { return GetData() + 1; }
|
FORCEINLINE constexpr FSentinel End() { return GetData() + 1; }
|
||||||
FORCEINLINE constexpr ConstSentinel End() const { return GetData() + 1; }
|
FORCEINLINE constexpr FConstSentinel End() const { return GetData() + 1; }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr T* GetData() { return AddressOf(Value); }
|
NODISCARD FORCEINLINE constexpr T* GetData() { return AddressOf(Value); }
|
||||||
NODISCARD FORCEINLINE constexpr const T* GetData() const { return AddressOf(Value); }
|
NODISCARD FORCEINLINE constexpr const T* GetData() const { return AddressOf(Value); }
|
||||||
@ -108,13 +108,13 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TRemoveCV<W>;
|
using FElementType = TRemoveCV<W>;
|
||||||
|
|
||||||
using Reference = W;
|
using FReference = W;
|
||||||
|
|
||||||
using Iterator = FIteratorImpl;
|
using FIterator = FIteratorImpl;
|
||||||
|
|
||||||
using Sentinel = TConditional<CSameAs<W, S>, FIteratorImpl, FSentinelImpl>;
|
using FSentinel = TConditional<CSameAs<W, S>, FIteratorImpl, FSentinelImpl>;
|
||||||
|
|
||||||
FORCEINLINE constexpr TIotaView() requires (CDefaultConstructible<W>) = default;
|
FORCEINLINE constexpr TIotaView() requires (CDefaultConstructible<W>) = default;
|
||||||
|
|
||||||
@ -122,13 +122,13 @@ public:
|
|||||||
|
|
||||||
FORCEINLINE constexpr explicit TIotaView(TIdentity<W> InValue, TIdentity<S> InLast) : First(InValue), Last(InLast) { }
|
FORCEINLINE constexpr explicit TIotaView(TIdentity<W> InValue, TIdentity<S> InLast) : First(InValue), Last(InLast) { }
|
||||||
|
|
||||||
FORCEINLINE constexpr explicit TIotaView(Iterator InFirst, Sentinel InLast) : First(InFirst.Value), Last(InLast.Value) { }
|
FORCEINLINE constexpr explicit TIotaView(FIterator InFirst, FSentinel InLast) : First(InFirst.Value), Last(InLast.Value) { }
|
||||||
|
|
||||||
FORCEINLINE constexpr explicit TIotaView(Iterator InFirst, FUnreachableSentinel) requires (CSameAs<S, FUnreachableSentinel>) : First(InFirst.Value) { }
|
FORCEINLINE constexpr explicit TIotaView(FIterator InFirst, FUnreachableSentinel) requires (CSameAs<S, FUnreachableSentinel>) : First(InFirst.Value) { }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(First); }
|
NODISCARD FORCEINLINE constexpr FIterator Begin() const { return FIterator(First); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr Sentinel End() const { return Sentinel(Last); }
|
NODISCARD FORCEINLINE constexpr FSentinel End() const { return FSentinel(Last); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr size_t Num() const requires ((CIntegral<W> && CIntegral<S>) || CSizedSentinelFor<S, W>) { return Last - First; }
|
NODISCARD FORCEINLINE constexpr size_t Num() const requires ((CIntegral<W> && CIntegral<S>) || CSizedSentinelFor<S, W>) { return Last - First; }
|
||||||
|
|
||||||
@ -143,13 +143,13 @@ private:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TRemoveCV<W>;
|
using FElementType = TRemoveCV<W>;
|
||||||
|
|
||||||
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<W>) = default;
|
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<W>) = default;
|
||||||
|
|
||||||
NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CEqualityComparable<W>) { return LHS.Value == RHS.Value; }
|
NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CEqualityComparable<W>) { return LHS.Value == RHS.Value; }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr Reference operator*() const { return Value; }
|
NODISCARD FORCEINLINE constexpr FReference operator*() const { return Value; }
|
||||||
NODISCARD FORCEINLINE constexpr const W* operator->() const { return AddressOf(Value); }
|
NODISCARD FORCEINLINE constexpr const W* operator->() const { return AddressOf(Value); }
|
||||||
|
|
||||||
FORCEINLINE constexpr FIteratorImpl& operator++() { ++Value; return *this; }
|
FORCEINLINE constexpr FIteratorImpl& operator++() { ++Value; return *this; }
|
||||||
@ -207,13 +207,13 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = W;
|
using FElementType = W;
|
||||||
|
|
||||||
using Reference = const W&;
|
using FReference = const W&;
|
||||||
|
|
||||||
using Iterator = FIteratorImpl;
|
using FIterator = FIteratorImpl;
|
||||||
|
|
||||||
using Sentinel = TConditional<bIsUnreachable, FUnreachableSentinel, Iterator>;
|
using FSentinel = TConditional<bIsUnreachable, FUnreachableSentinel, FIterator>;
|
||||||
|
|
||||||
FORCEINLINE constexpr TRepeatView() requires (CDefaultConstructible<W>) = default;
|
FORCEINLINE constexpr TRepeatView() requires (CDefaultConstructible<W>) = default;
|
||||||
|
|
||||||
@ -228,16 +228,16 @@ public:
|
|||||||
template <typename... Ts> requires (CConstructibleFrom<W, Ts...>)
|
template <typename... Ts> requires (CConstructibleFrom<W, Ts...>)
|
||||||
FORCEINLINE constexpr explicit TRepeatView(FInPlace, Ts&&... Args, size_t InCount) : Value(Forward<Ts>(Args)...), Count(InCount) { }
|
FORCEINLINE constexpr explicit TRepeatView(FInPlace, Ts&&... Args, size_t InCount) : Value(Forward<Ts>(Args)...), Count(InCount) { }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(Value, 0); }
|
NODISCARD FORCEINLINE constexpr FIterator Begin() const { return FIterator(Value, 0); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr Sentinel End() const
|
NODISCARD FORCEINLINE constexpr FSentinel End() const
|
||||||
{
|
{
|
||||||
if constexpr (bIsUnreachable)
|
if constexpr (bIsUnreachable)
|
||||||
{
|
{
|
||||||
return UnreachableSentinel;
|
return UnreachableSentinel;
|
||||||
}
|
}
|
||||||
|
|
||||||
else return Sentinel(Value, Count);
|
else return FSentinel(Value, Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr size_t Num() const requires (!bIsUnreachable) { return Count; }
|
NODISCARD FORCEINLINE constexpr size_t Num() const requires (!bIsUnreachable) { return Count; }
|
||||||
@ -254,7 +254,7 @@ private:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = W;
|
using FElementType = W;
|
||||||
|
|
||||||
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<W>) = default;
|
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<W>) = default;
|
||||||
|
|
||||||
@ -262,10 +262,10 @@ private:
|
|||||||
|
|
||||||
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const FIteratorImpl& LHS, const FIteratorImpl& RHS) { return LHS.Current <=> RHS.Current; }
|
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const FIteratorImpl& LHS, const FIteratorImpl& RHS) { return LHS.Current <=> RHS.Current; }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr Reference operator*() const { return *Ptr; }
|
NODISCARD FORCEINLINE constexpr FReference operator*() const { return *Ptr; }
|
||||||
NODISCARD FORCEINLINE constexpr const W* operator->() const { return Ptr; }
|
NODISCARD FORCEINLINE constexpr const W* operator->() const { return Ptr; }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr Reference operator[](ptrdiff) const { return *Ptr; }
|
NODISCARD FORCEINLINE constexpr FReference operator[](ptrdiff) const { return *Ptr; }
|
||||||
|
|
||||||
FORCEINLINE constexpr FIteratorImpl& operator++() { ++Current; return *this; }
|
FORCEINLINE constexpr FIteratorImpl& operator++() { ++Current; return *this; }
|
||||||
FORCEINLINE constexpr FIteratorImpl& operator--() { --Current; return *this; }
|
FORCEINLINE constexpr FIteratorImpl& operator--() { --Current; return *this; }
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "CoreTypes.h"
|
#include "CoreTypes.h"
|
||||||
#include "Range/View.h"
|
#include "Range/View.h"
|
||||||
|
#include "Range/Pipe.h"
|
||||||
#include "Range/Utility.h"
|
#include "Range/Utility.h"
|
||||||
#include "Range/AllView.h"
|
#include "Range/AllView.h"
|
||||||
#include "Memory/Address.h"
|
#include "Memory/Address.h"
|
||||||
@ -30,20 +31,20 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TRangeElement<V>;
|
using FElementType = TRangeElement<V>;
|
||||||
using Reference = TRangeReference<V>;
|
using FReference = TRangeReference<V>;
|
||||||
|
|
||||||
using Iterator = FIteratorImpl;
|
using FIterator = FIteratorImpl;
|
||||||
|
|
||||||
using Sentinel = TConditional<CCommonRange<V>, FIteratorImpl, FSentinelImpl>;
|
using FSentinel = TConditional<CCommonRange<V>, FIteratorImpl, FSentinelImpl>;
|
||||||
|
|
||||||
FORCEINLINE constexpr TFilterView() requires (CDefaultConstructible<V> && CDefaultConstructible<Pred>) = default;
|
FORCEINLINE constexpr TFilterView() requires (CDefaultConstructible<V> && CDefaultConstructible<Pred>) = default;
|
||||||
|
|
||||||
FORCEINLINE constexpr explicit TFilterView(V InBase, Pred InPredicate) : Base(MoveTemp(InBase)), Predicate(MoveTemp(InPredicate)) { }
|
FORCEINLINE constexpr explicit TFilterView(V InBase, Pred InPredicate) : Base(MoveTemp(InBase)), Predicate(MoveTemp(InPredicate)) { }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr Iterator Begin()
|
NODISCARD FORCEINLINE constexpr FIterator Begin()
|
||||||
{
|
{
|
||||||
Iterator Iter(*this, Range::Begin(Base));
|
FIterator Iter(*this, Range::Begin(Base));
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -60,7 +61,7 @@ public:
|
|||||||
return Iter;
|
return Iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr Sentinel End() { return Sentinel(*this, Range::End(Base)); }
|
NODISCARD FORCEINLINE constexpr FSentinel End() { return FSentinel(*this, Range::End(Base)); }
|
||||||
|
|
||||||
NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible<V>) { return Base; }
|
NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible<V>) { return Base; }
|
||||||
NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); }
|
NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); }
|
||||||
@ -78,7 +79,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TIteratorElementType<TRangeIterator<V>>;
|
using FElementType = TIteratorElementType<TRangeIterator<V>>;
|
||||||
|
|
||||||
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<V>>) { } // Use '{ }' instead of '= default;' to avoid MSVC bug.
|
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<V>>) { } // Use '{ }' instead of '= default;' to avoid MSVC bug.
|
||||||
|
|
||||||
@ -174,10 +175,10 @@ NODISCARD FORCEINLINE constexpr auto Filter(R&& Base, Pred&& Predicate)
|
|||||||
template <typename Pred>
|
template <typename Pred>
|
||||||
NODISCARD FORCEINLINE constexpr auto Filter(Pred&& Predicate)
|
NODISCARD FORCEINLINE constexpr auto Filter(Pred&& Predicate)
|
||||||
{
|
{
|
||||||
return [&Predicate]<CViewableRange R> requires (requires { TFilterView(DeclVal<R&&>(), DeclVal<Pred&&>()); }) (R&& Base)
|
return TAdaptorClosure([&Predicate]<CViewableRange R> requires (requires { Range::Filter(DeclVal<R&&>(), DeclVal<Pred&&>()); }) (R&& Base)
|
||||||
{
|
{
|
||||||
return TFilterView(Forward<R>(Base), Forward<Pred>(Predicate));
|
return Range::Filter(Forward<R>(Base), Forward<Pred>(Predicate));
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
NAMESPACE_END(Range)
|
NAMESPACE_END(Range)
|
||||||
|
119
Redcraft.Utility/Source/Public/Range/Pipe.h
Normal file
119
Redcraft.Utility/Source/Public/Range/Pipe.h
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreTypes.h"
|
||||||
|
#include "Range/Utility.h"
|
||||||
|
#include "Templates/Invoke.h"
|
||||||
|
#include "Templates/Utility.h"
|
||||||
|
#include "TypeTraits/TypeTraits.h"
|
||||||
|
|
||||||
|
NAMESPACE_REDCRAFT_BEGIN
|
||||||
|
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||||
|
NAMESPACE_MODULE_BEGIN(Utility)
|
||||||
|
|
||||||
|
NAMESPACE_BEGIN(Range)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface class template for defining a range adaptor closure.
|
||||||
|
* When the derived class has a unary operator() with range as a reference and is not itself a range,
|
||||||
|
* the derived class is the range adaptor closure type and its objects can participate in pipe operations.
|
||||||
|
* Specify, the unary operator() with any reference qualifier or cv-qualifier must be defined and has same effect.
|
||||||
|
* Not directly instantiable.
|
||||||
|
*/
|
||||||
|
template <CObject D> requires (CSameAs<D, TRemoveCV<D>>)
|
||||||
|
class IAdaptorClosure { };
|
||||||
|
|
||||||
|
/** An adaptor closure helper that wraps a callable object. */
|
||||||
|
template <CMoveConstructible F>
|
||||||
|
class TAdaptorClosure : public IAdaptorClosure<TAdaptorClosure<F>>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
FORCEINLINE constexpr explicit TAdaptorClosure(F InClosure) : Closure(MoveTemp(InClosure)) { }
|
||||||
|
|
||||||
|
template <typename R> requires (CInvocable<F&, R>)
|
||||||
|
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) &
|
||||||
|
{
|
||||||
|
return Invoke(Closure, Forward<R>(Range));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R> requires (CInvocable<const F&, R>)
|
||||||
|
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&
|
||||||
|
{
|
||||||
|
return Invoke(Closure, Forward<R>(Range));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R> requires (CInvocable<F&&, R>)
|
||||||
|
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) &&
|
||||||
|
{
|
||||||
|
return Invoke(MoveTemp(Closure), Forward<R>(Range));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R> requires (CInvocable<const F&&, R>)
|
||||||
|
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&&
|
||||||
|
{
|
||||||
|
return Invoke(MoveTemp(Closure), Forward<R>(Range));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
NO_UNIQUE_ADDRESS F Closure;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A pipe closure that wraps two adaptor closures. */
|
||||||
|
template <CMoveConstructible T, CMoveConstructible U> requires (CDerivedFrom<T, IAdaptorClosure<T>> && CDerivedFrom<U, IAdaptorClosure<U>>)
|
||||||
|
class TPipeClosure final : public IAdaptorClosure<TPipeClosure<T, U>>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
FORCEINLINE constexpr explicit TPipeClosure(T InLHS, U InRHS) : LHS(MoveTemp(InLHS)), RHS(MoveTemp(InRHS)) { }
|
||||||
|
|
||||||
|
template <typename R> requires (CInvocable<T&, R> && CInvocable<U&, TInvokeResult<T&, R>>)
|
||||||
|
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) &
|
||||||
|
{
|
||||||
|
return Forward<R>(Range) | LHS | RHS;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R> requires (CInvocable<const T&, R> && CInvocable<const U&, TInvokeResult<const T&, R>>)
|
||||||
|
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&
|
||||||
|
{
|
||||||
|
return Forward<R>(Range) | LHS | RHS;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R> requires (CInvocable<T&&, R> && CInvocable<U&&, TInvokeResult<T&&, R>>)
|
||||||
|
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) &&
|
||||||
|
{
|
||||||
|
return Forward<R>(Range) | MoveTemp(LHS) | MoveTemp(RHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R> requires (CInvocable<const T&&, R> && CInvocable<const U&&, TInvokeResult<const T&&, R>>)
|
||||||
|
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&&
|
||||||
|
{
|
||||||
|
return Forward<R>(Range) | MoveTemp(LHS) | MoveTemp(RHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
NO_UNIQUE_ADDRESS T LHS;
|
||||||
|
NO_UNIQUE_ADDRESS U RHS;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Apply the range adaptor closure to the range. */
|
||||||
|
template <CRange R, CInvocable<R> T> requires (CDerivedFrom<TRemoveCVRef<T>, IAdaptorClosure<TRemoveCVRef<T>>>)
|
||||||
|
NODISCARD FORCEINLINE constexpr auto operator|(R&& Range, T&& Closure)
|
||||||
|
{
|
||||||
|
return Invoke(Forward<T>(Closure), Forward<R>(Range));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a pipe closure that wraps two adaptor closures. */
|
||||||
|
template <CMoveConstructible T, CMoveConstructible U> requires (CDerivedFrom<T, IAdaptorClosure<T>> && CDerivedFrom<U, IAdaptorClosure<U>>)
|
||||||
|
NODISCARD FORCEINLINE constexpr auto operator|(T LHS, U RHS)
|
||||||
|
{
|
||||||
|
return TPipeClosure(MoveTemp(LHS), MoveTemp(RHS));
|
||||||
|
}
|
||||||
|
|
||||||
|
NAMESPACE_END(Range)
|
||||||
|
|
||||||
|
NAMESPACE_MODULE_END(Utility)
|
||||||
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
|
NAMESPACE_REDCRAFT_END
|
@ -4,6 +4,7 @@
|
|||||||
#include "Range/Utility.h"
|
#include "Range/Utility.h"
|
||||||
#include "Range/View.h"
|
#include "Range/View.h"
|
||||||
#include "Range/Factory.h"
|
#include "Range/Factory.h"
|
||||||
|
#include "Range/Pipe.h"
|
||||||
#include "Range/AllView.h"
|
#include "Range/AllView.h"
|
||||||
#include "Range/FilterView.h"
|
#include "Range/FilterView.h"
|
||||||
#include "Range/TransformView.h"
|
#include "Range/TransformView.h"
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "CoreTypes.h"
|
#include "CoreTypes.h"
|
||||||
#include "Range/View.h"
|
#include "Range/View.h"
|
||||||
|
#include "Range/Pipe.h"
|
||||||
#include "Range/Utility.h"
|
#include "Range/Utility.h"
|
||||||
#include "Range/AllView.h"
|
#include "Range/AllView.h"
|
||||||
#include "Templates/Invoke.h"
|
#include "Templates/Invoke.h"
|
||||||
@ -88,7 +89,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TRemoveCVRef<TInvokeResult<FFunc&, TRangeReference<FBase>>>;
|
using FElementType = TRemoveCVRef<TInvokeResult<FFunc&, TRangeReference<FBase>>>;
|
||||||
|
|
||||||
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<FBase>>) = default;
|
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<FBase>>) = default;
|
||||||
|
|
||||||
@ -221,10 +222,10 @@ NODISCARD FORCEINLINE constexpr auto Transform(R&& Base, F&& Func)
|
|||||||
template <typename F>
|
template <typename F>
|
||||||
NODISCARD FORCEINLINE constexpr auto Transform(F&& Func)
|
NODISCARD FORCEINLINE constexpr auto Transform(F&& Func)
|
||||||
{
|
{
|
||||||
return [&Func]<CViewableRange R> requires (requires { TTransformView(DeclVal<R&&>(), DeclVal<F&&>()); }) (R&& Base)
|
return TAdaptorClosure([&Func]<CViewableRange R> requires (requires { Range::Transform(DeclVal<R&&>(), DeclVal<F&&>()); }) (R&& Base)
|
||||||
{
|
{
|
||||||
return TTransformView(Forward<R>(Base), Forward<F>(Func));
|
return Range::Transform(Forward<R>(Base), Forward<F>(Func));
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
NAMESPACE_END(Range)
|
NAMESPACE_END(Range)
|
||||||
|
@ -11,7 +11,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
|
|||||||
|
|
||||||
NAMESPACE_BEGIN(Range)
|
NAMESPACE_BEGIN(Range)
|
||||||
|
|
||||||
/** A helper class template for defining a view interface. Not directly instantiable. */
|
/** An interface class template for defining a view. Not directly instantiable. */
|
||||||
template <CClass T> requires (CSameAs<T, TRemoveCV<T>>)
|
template <CClass T> requires (CSameAs<T, TRemoveCV<T>>)
|
||||||
class IBasicViewInterface
|
class IBasicViewInterface
|
||||||
{
|
{
|
||||||
@ -100,7 +100,7 @@ class TRangeView : public IBasicViewInterface<TRangeView<I, S>>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TIteratorElementType<I>;
|
using FElementType = TIteratorElementType<I>;
|
||||||
|
|
||||||
FORCEINLINE constexpr TRangeView() requires (CDefaultConstructible<I>) = default;
|
FORCEINLINE constexpr TRangeView() requires (CDefaultConstructible<I>) = default;
|
||||||
|
|
||||||
|
@ -68,31 +68,31 @@ static_assert(CUnsigned<unicodechar>, "TChar assumes unicodechar is an unsigned
|
|||||||
template <CCharType T>
|
template <CCharType T>
|
||||||
struct TChar
|
struct TChar
|
||||||
{
|
{
|
||||||
using CharType = T;
|
using FCharType = T;
|
||||||
|
|
||||||
/** The maximum number of code units required to represent a single character. if unknown, guess 1. */
|
/** The maximum number of code units required to represent a single character. if unknown, guess 1. */
|
||||||
static constexpr size_t MaxCodeUnitLength =
|
static constexpr size_t MaxCodeUnitLength =
|
||||||
CSameAs<CharType, char> ? MB_LEN_MAX :
|
CSameAs<FCharType, char> ? MB_LEN_MAX :
|
||||||
CSameAs<CharType, wchar> ?
|
CSameAs<FCharType, wchar> ?
|
||||||
PLATFORM_WINDOWS ? 2 :
|
PLATFORM_WINDOWS ? 2 :
|
||||||
PLATFORM_LINUX ? 1 : 1 :
|
PLATFORM_LINUX ? 1 : 1 :
|
||||||
CSameAs<CharType, u8char> ? 4 :
|
CSameAs<FCharType, u8char> ? 4 :
|
||||||
CSameAs<CharType, u16char> ? 2 :
|
CSameAs<FCharType, u16char> ? 2 :
|
||||||
CSameAs<CharType, u32char> ? 1 : 1;
|
CSameAs<FCharType, u32char> ? 1 : 1;
|
||||||
|
|
||||||
/** Whether the character type is fixed-length. */
|
/** Whether the character type is fixed-length. */
|
||||||
static constexpr bool bIsFixedLength = MaxCodeUnitLength == 1;
|
static constexpr bool bIsFixedLength = MaxCodeUnitLength == 1;
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsValid(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsValid(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, u8char>)
|
if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
if ((InChar & 0b10000000) == 0b00000000) return true;
|
if ((InChar & 0b10000000) == 0b00000000) return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char> || CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u16char> || CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
if (InChar >= 0xD800 && InChar <= 0xDBFF) return false;
|
if (InChar >= 0xD800 && InChar <= 0xDBFF) return false;
|
||||||
if (InChar >= 0xDC00 && InChar <= 0xDFFF) return false;
|
if (InChar >= 0xDC00 && InChar <= 0xDFFF) return false;
|
||||||
@ -101,30 +101,30 @@ struct TChar
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Windows uses UTF-16 encoding for wchar.
|
// Windows uses UTF-16 encoding for wchar.
|
||||||
else if constexpr (PLATFORM_WINDOWS && (CSameAs<CharType, wchar>))
|
else if constexpr (PLATFORM_WINDOWS && (CSameAs<FCharType, wchar>))
|
||||||
{
|
{
|
||||||
return TChar::IsValid(static_cast<u16char>(InChar));
|
return TChar::IsValid(static_cast<u16char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Linux uses UTF-32 encoding for wchar.
|
// Linux uses UTF-32 encoding for wchar.
|
||||||
else if constexpr (PLATFORM_LINUX && (CSameAs<CharType, wchar>))
|
else if constexpr (PLATFORM_LINUX && (CSameAs<FCharType, wchar>))
|
||||||
{
|
{
|
||||||
return TChar::IsValid(static_cast<u32char>(InChar));
|
return TChar::IsValid(static_cast<u32char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsNonch(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsNonch(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, u8char>)
|
if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char>)
|
else if constexpr (CSameAs<FCharType, u16char>)
|
||||||
{
|
{
|
||||||
if (InChar >= U16TEXT('\uFDD0') && InChar <= U16TEXT('\uFDEF')) return true;
|
if (InChar >= U16TEXT('\uFDD0') && InChar <= U16TEXT('\uFDEF')) return true;
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ struct TChar
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
if (InChar >= U32TEXT('\uFDD0') && InChar <= U32TEXT('\uFDEF')) return true;
|
if (InChar >= U32TEXT('\uFDD0') && InChar <= U32TEXT('\uFDEF')) return true;
|
||||||
|
|
||||||
@ -144,25 +144,25 @@ struct TChar
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Windows uses UTF-16 encoding for wchar.
|
// Windows uses UTF-16 encoding for wchar.
|
||||||
else if constexpr (PLATFORM_WINDOWS && (CSameAs<CharType, wchar>))
|
else if constexpr (PLATFORM_WINDOWS && (CSameAs<FCharType, wchar>))
|
||||||
{
|
{
|
||||||
return TChar::IsNonch(static_cast<u16char>(InChar));
|
return TChar::IsNonch(static_cast<u16char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Linux uses UTF-32 encoding for wchar.
|
// Linux uses UTF-32 encoding for wchar.
|
||||||
else if constexpr (PLATFORM_LINUX && (CSameAs<CharType, wchar>))
|
else if constexpr (PLATFORM_LINUX && (CSameAs<FCharType, wchar>))
|
||||||
{
|
{
|
||||||
return TChar::IsNonch(static_cast<u32char>(InChar));
|
return TChar::IsNonch(static_cast<u32char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsASCII(CharType InChar = LITERAL(CharType, '\0'))
|
NODISCARD FORCEINLINE static constexpr bool IsASCII(FCharType InChar = LITERAL(FCharType, '\0'))
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char>)
|
if constexpr (CSameAs<FCharType, char>)
|
||||||
{
|
{
|
||||||
constexpr bool ASCIICompatible = []() -> bool
|
constexpr bool ASCIICompatible = []() -> bool
|
||||||
{
|
{
|
||||||
@ -188,7 +188,7 @@ struct TChar
|
|||||||
return ASCIICompatible && 0x00 <= InChar && InChar <= 0x7F;
|
return ASCIICompatible && 0x00 <= InChar && InChar <= 0x7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, wchar>)
|
else if constexpr (CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
constexpr bool ASCIICompatible = []() -> bool
|
constexpr bool ASCIICompatible = []() -> bool
|
||||||
{
|
{
|
||||||
@ -214,19 +214,19 @@ struct TChar
|
|||||||
return ASCIICompatible && 0x00 <= InChar && InChar <= 0x7F;
|
return ASCIICompatible && 0x00 <= InChar && InChar <= 0x7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char> || CSameAs<CharType, u16char> || CSameAs<CharType, u32char> || CSameAs<CharType, unicodechar>)
|
else if constexpr (CSameAs<FCharType, u8char> || CSameAs<FCharType, u16char> || CSameAs<FCharType, u32char> || CSameAs<FCharType, unicodechar>)
|
||||||
{
|
{
|
||||||
return InChar <= 0x7F;
|
return InChar <= 0x7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsAlnum(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsAlnum(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return NAMESPACE_STD::isalnum(InChar, Loc);
|
return NAMESPACE_STD::isalnum(InChar, Loc);
|
||||||
@ -237,15 +237,15 @@ struct TChar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsAlpha(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsAlpha(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return NAMESPACE_STD::isalpha(InChar, Loc);
|
return NAMESPACE_STD::isalpha(InChar, Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char>)
|
else if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* BASIC LATIN
|
* BASIC LATIN
|
||||||
@ -258,29 +258,29 @@ struct TChar
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char> || CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u16char> || CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= LITERAL(CharType, '\u007F'), TEXT("TChar::IsAlpha() only supports basic latin block."));
|
checkf(InChar <= LITERAL(FCharType, '\u007F'), TEXT("TChar::IsAlpha() only supports basic latin block."));
|
||||||
|
|
||||||
if (InChar > LITERAL(CharType, '\u007F')) return false;
|
if (InChar > LITERAL(FCharType, '\u007F')) return false;
|
||||||
|
|
||||||
return TChar<u8char>::IsAlpha(static_cast<u8char>(InChar));
|
return TChar<u8char>::IsAlpha(static_cast<u8char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsLower(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsLower(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return NAMESPACE_STD::islower(InChar, Loc);
|
return NAMESPACE_STD::islower(InChar, Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char>)
|
else if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* BASIC LATIN
|
* BASIC LATIN
|
||||||
@ -291,7 +291,7 @@ struct TChar
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char>)
|
else if constexpr (CSameAs<FCharType, u16char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsLower() only supports basic latin block."));
|
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsLower() only supports basic latin block."));
|
||||||
|
|
||||||
@ -300,7 +300,7 @@ struct TChar
|
|||||||
return TChar<u8char>::IsLower(static_cast<u8char>(InChar));
|
return TChar<u8char>::IsLower(static_cast<u8char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsLower() only supports basic latin block."));
|
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsLower() only supports basic latin block."));
|
||||||
|
|
||||||
@ -309,20 +309,20 @@ struct TChar
|
|||||||
return TChar<u8char>::IsLower(static_cast<u8char>(InChar));
|
return TChar<u8char>::IsLower(static_cast<u8char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsUpper(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsUpper(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return NAMESPACE_STD::isupper(InChar, Loc);
|
return NAMESPACE_STD::isupper(InChar, Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char>)
|
else if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* BASIC LATIN
|
* BASIC LATIN
|
||||||
@ -333,7 +333,7 @@ struct TChar
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char>)
|
else if constexpr (CSameAs<FCharType, u16char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsUpper() only supports basic latin block."));
|
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsUpper() only supports basic latin block."));
|
||||||
|
|
||||||
@ -342,7 +342,7 @@ struct TChar
|
|||||||
return TChar<u8char>::IsUpper(static_cast<u8char>(InChar));
|
return TChar<u8char>::IsUpper(static_cast<u8char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsUpper() only supports basic latin block."));
|
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsUpper() only supports basic latin block."));
|
||||||
|
|
||||||
@ -351,20 +351,20 @@ struct TChar
|
|||||||
return TChar<u8char>::IsUpper(static_cast<u8char>(InChar));
|
return TChar<u8char>::IsUpper(static_cast<u8char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsDigit(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsDigit(FCharType InChar)
|
||||||
{
|
{
|
||||||
static_assert(TChar::IsASCII());
|
static_assert(TChar::IsASCII());
|
||||||
|
|
||||||
/* <U0030>..<U0039>; */
|
/* <U0030>..<U0039>; */
|
||||||
return InChar >= LITERAL(CharType, '0') && InChar <= LITERAL(CharType, '9');
|
return InChar >= LITERAL(FCharType, '0') && InChar <= LITERAL(FCharType, '9');
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsDigit(CharType InChar, unsigned Base)
|
NODISCARD FORCEINLINE static constexpr bool IsDigit(FCharType InChar, unsigned Base)
|
||||||
{
|
{
|
||||||
checkf(Base >= 2 && Base <= 36, TEXT("Base must be in the range [2, 36]."));
|
checkf(Base >= 2 && Base <= 36, TEXT("Base must be in the range [2, 36]."));
|
||||||
|
|
||||||
@ -373,32 +373,32 @@ struct TChar
|
|||||||
bool bResult = false;
|
bool bResult = false;
|
||||||
|
|
||||||
/* <U0030>..<U0039>; */
|
/* <U0030>..<U0039>; */
|
||||||
bResult |= InChar >= LITERAL(CharType, '0') && InChar < LITERAL(CharType, '0') + static_cast<signed>(Base);
|
bResult |= InChar >= LITERAL(FCharType, '0') && InChar < LITERAL(FCharType, '0') + static_cast<signed>(Base);
|
||||||
|
|
||||||
/* <U0041>..<U0046>; */
|
/* <U0041>..<U0046>; */
|
||||||
bResult |= InChar >= LITERAL(CharType, 'a') && InChar < LITERAL(CharType, 'a') + static_cast<signed>(Base) - 10;
|
bResult |= InChar >= LITERAL(FCharType, 'a') && InChar < LITERAL(FCharType, 'a') + static_cast<signed>(Base) - 10;
|
||||||
|
|
||||||
/* <U0061>..<U0066>; */
|
/* <U0061>..<U0066>; */
|
||||||
bResult |= InChar >= LITERAL(CharType, 'A') && InChar < LITERAL(CharType, 'A') + static_cast<signed>(Base) - 10;
|
bResult |= InChar >= LITERAL(FCharType, 'A') && InChar < LITERAL(FCharType, 'A') + static_cast<signed>(Base) - 10;
|
||||||
|
|
||||||
return bResult;
|
return bResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsCntrl(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsCntrl(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return NAMESPACE_STD::iscntrl(InChar, Loc);
|
return NAMESPACE_STD::iscntrl(InChar, Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char>)
|
else if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
/* <U0000>..<U001F>;<U007F>; */
|
/* <U0000>..<U001F>;<U007F>; */
|
||||||
return (InChar >= U8TEXT('\u0000') && InChar <= U8TEXT('\u001F')) || InChar == U8TEXT('\u007F');
|
return (InChar >= U8TEXT('\u0000') && InChar <= U8TEXT('\u001F')) || InChar == U8TEXT('\u007F');
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char>)
|
else if constexpr (CSameAs<FCharType, u16char>)
|
||||||
{
|
{
|
||||||
/* <U0000>..<U001F>;<U007F>..<U009F>;<U2028>;<U2029>; */
|
/* <U0000>..<U001F>;<U007F>..<U009F>;<U2028>;<U2029>; */
|
||||||
return
|
return
|
||||||
@ -407,7 +407,7 @@ struct TChar
|
|||||||
(InChar == U16TEXT('\u2028') || InChar == U16TEXT('\u2029'));
|
(InChar == U16TEXT('\u2028') || InChar == U16TEXT('\u2029'));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
/* <U0000>..<U001F>;<U007F>..<U009F>;<U2028>;<U2029>; */
|
/* <U0000>..<U001F>;<U007F>..<U009F>;<U2028>;<U2029>; */
|
||||||
return
|
return
|
||||||
@ -416,20 +416,20 @@ struct TChar
|
|||||||
(InChar == U32TEXT('\u2028') || InChar == U32TEXT('\u2029'));
|
(InChar == U32TEXT('\u2028') || InChar == U32TEXT('\u2029'));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsGraph(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsGraph(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return NAMESPACE_STD::isgraph(InChar, Loc);
|
return NAMESPACE_STD::isgraph(InChar, Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char>)
|
else if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* BASIC LATIN
|
* BASIC LATIN
|
||||||
@ -440,7 +440,7 @@ struct TChar
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char>)
|
else if constexpr (CSameAs<FCharType, u16char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsGraph() only supports basic latin block."));
|
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsGraph() only supports basic latin block."));
|
||||||
|
|
||||||
@ -449,7 +449,7 @@ struct TChar
|
|||||||
return TChar<u8char>::IsGraph(static_cast<u8char>(InChar));
|
return TChar<u8char>::IsGraph(static_cast<u8char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsGraph() only supports basic latin block."));
|
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsGraph() only supports basic latin block."));
|
||||||
|
|
||||||
@ -458,20 +458,20 @@ struct TChar
|
|||||||
return TChar<u8char>::IsGraph(static_cast<u8char>(InChar));
|
return TChar<u8char>::IsGraph(static_cast<u8char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsSpace(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsSpace(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return NAMESPACE_STD::isspace(InChar, Loc);
|
return NAMESPACE_STD::isspace(InChar, Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char>)
|
else if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* ISO/IEC 6429
|
* ISO/IEC 6429
|
||||||
@ -488,7 +488,7 @@ struct TChar
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char>)
|
else if constexpr (CSameAs<FCharType, u16char>)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* ISO/IEC 6429
|
* ISO/IEC 6429
|
||||||
@ -533,7 +533,7 @@ struct TChar
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* ISO/IEC 6429
|
* ISO/IEC 6429
|
||||||
@ -578,26 +578,26 @@ struct TChar
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsBlank(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsBlank(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return NAMESPACE_STD::isblank(InChar, Loc);
|
return NAMESPACE_STD::isblank(InChar, Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char>)
|
else if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
/* <U0009>;<U0020>; */
|
/* <U0009>;<U0020>; */
|
||||||
return InChar == U8TEXT('\u0009') || InChar == U8TEXT('\u0020');
|
return InChar == U8TEXT('\u0009') || InChar == U8TEXT('\u0020');
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char>)
|
else if constexpr (CSameAs<FCharType, u16char>)
|
||||||
{
|
{
|
||||||
/* <U0009>;<U0020>;<U1680>;<U180E>;<U2000>..<U2006>;<U2008>..<U200A>;<U205F>;<U3000>; */
|
/* <U0009>;<U0020>;<U1680>;<U180E>;<U2000>..<U2006>;<U2008>..<U200A>;<U205F>;<U3000>; */
|
||||||
return
|
return
|
||||||
@ -608,7 +608,7 @@ struct TChar
|
|||||||
(InChar == U16TEXT('\u205F') || InChar == U16TEXT('\u3000'));
|
(InChar == U16TEXT('\u205F') || InChar == U16TEXT('\u3000'));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
/* <U0009>;<U0020>;<U1680>;<U180E>;<U2000>..<U2006>;<U2008>..<U200A>;<U205F>;<U3000>; */
|
/* <U0009>;<U0020>;<U1680>;<U180E>;<U2000>..<U2006>;<U2008>..<U200A>;<U205F>;<U3000>; */
|
||||||
return
|
return
|
||||||
@ -619,20 +619,20 @@ struct TChar
|
|||||||
(InChar == U32TEXT('\u205F') || InChar == U32TEXT('\u3000'));
|
(InChar == U32TEXT('\u205F') || InChar == U32TEXT('\u3000'));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsPrint(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsPrint(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return NAMESPACE_STD::isprint(InChar, Loc);
|
return NAMESPACE_STD::isprint(InChar, Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char>)
|
else if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* BASIC LATIN
|
* BASIC LATIN
|
||||||
@ -643,7 +643,7 @@ struct TChar
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char>)
|
else if constexpr (CSameAs<FCharType, u16char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsPrint() only supports basic latin block."));
|
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsPrint() only supports basic latin block."));
|
||||||
|
|
||||||
@ -652,7 +652,7 @@ struct TChar
|
|||||||
return TChar<u8char>::IsPrint(static_cast<u8char>(InChar));
|
return TChar<u8char>::IsPrint(static_cast<u8char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsPrint() only supports basic latin block."));
|
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsPrint() only supports basic latin block."));
|
||||||
|
|
||||||
@ -661,20 +661,20 @@ struct TChar
|
|||||||
return TChar<u8char>::IsPrint(static_cast<u8char>(InChar));
|
return TChar<u8char>::IsPrint(static_cast<u8char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr bool IsPunct(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr bool IsPunct(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return NAMESPACE_STD::ispunct(InChar, Loc);
|
return NAMESPACE_STD::ispunct(InChar, Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char>)
|
else if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* BASIC LATIN
|
* BASIC LATIN
|
||||||
@ -689,7 +689,7 @@ struct TChar
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char>)
|
else if constexpr (CSameAs<FCharType, u16char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsPunct() only supports basic latin block."));
|
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::IsPunct() only supports basic latin block."));
|
||||||
|
|
||||||
@ -698,7 +698,7 @@ struct TChar
|
|||||||
return TChar<u8char>::IsPunct(static_cast<u8char>(InChar));
|
return TChar<u8char>::IsPunct(static_cast<u8char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsPunct() only supports basic latin block."));
|
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::IsPunct() only supports basic latin block."));
|
||||||
|
|
||||||
@ -707,20 +707,20 @@ struct TChar
|
|||||||
return TChar<u8char>::IsPunct(static_cast<u8char>(InChar));
|
return TChar<u8char>::IsPunct(static_cast<u8char>(InChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr CharType ToLower(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr FCharType ToLower(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return static_cast<CharType>(NAMESPACE_STD::tolower(InChar, Loc));
|
return static_cast<FCharType>(NAMESPACE_STD::tolower(InChar, Loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char>)
|
else if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* BASIC LATIN
|
* BASIC LATIN
|
||||||
@ -737,7 +737,7 @@ struct TChar
|
|||||||
return InChar;
|
return InChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char>)
|
else if constexpr (CSameAs<FCharType, u16char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::ToLower() only supports basic latin block."));
|
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::ToLower() only supports basic latin block."));
|
||||||
|
|
||||||
@ -746,7 +746,7 @@ struct TChar
|
|||||||
return static_cast<u16char>(TChar<u8char>::ToLower(static_cast<u8char>(InChar)));
|
return static_cast<u16char>(TChar<u8char>::ToLower(static_cast<u8char>(InChar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::ToLower() only supports basic latin block."));
|
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::ToLower() only supports basic latin block."));
|
||||||
|
|
||||||
@ -755,20 +755,20 @@ struct TChar
|
|||||||
return static_cast<u16char>(TChar<u8char>::ToLower(static_cast<u8char>(InChar)));
|
return static_cast<u16char>(TChar<u8char>::ToLower(static_cast<u8char>(InChar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return InChar;
|
return InChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr CharType ToUpper(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr FCharType ToUpper(FCharType InChar)
|
||||||
{
|
{
|
||||||
if constexpr (CSameAs<CharType, char> || CSameAs<CharType, wchar>)
|
if constexpr (CSameAs<FCharType, char> || CSameAs<FCharType, wchar>)
|
||||||
{
|
{
|
||||||
NAMESPACE_STD::locale Loc("");
|
NAMESPACE_STD::locale Loc("");
|
||||||
return static_cast<CharType>(NAMESPACE_STD::toupper(InChar, Loc));
|
return static_cast<FCharType>(NAMESPACE_STD::toupper(InChar, Loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u8char>)
|
else if constexpr (CSameAs<FCharType, u8char>)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* BASIC LATIN
|
* BASIC LATIN
|
||||||
@ -785,7 +785,7 @@ struct TChar
|
|||||||
return InChar;
|
return InChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u16char>)
|
else if constexpr (CSameAs<FCharType, u16char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::ToUpper() only supports basic latin block."));
|
checkf(InChar <= U16TEXT('\u007F'), TEXT("TChar::ToUpper() only supports basic latin block."));
|
||||||
|
|
||||||
@ -794,7 +794,7 @@ struct TChar
|
|||||||
return static_cast<u16char>(TChar<u8char>::ToUpper(static_cast<u8char>(InChar)));
|
return static_cast<u16char>(TChar<u8char>::ToUpper(static_cast<u8char>(InChar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (CSameAs<CharType, u32char>)
|
else if constexpr (CSameAs<FCharType, u32char>)
|
||||||
{
|
{
|
||||||
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::ToUpper() only supports basic latin block."));
|
checkf(InChar <= U32TEXT('\u007F'), TEXT("TChar::ToUpper() only supports basic latin block."));
|
||||||
|
|
||||||
@ -803,12 +803,12 @@ struct TChar
|
|||||||
return static_cast<u16char>(TChar<u8char>::ToUpper(static_cast<u8char>(InChar)));
|
return static_cast<u16char>(TChar<u8char>::ToUpper(static_cast<u8char>(InChar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
else static_assert(sizeof(CharType) == -1, "Unsupported character type");
|
else static_assert(sizeof(FCharType) == -1, "Unsupported character type");
|
||||||
|
|
||||||
return InChar;
|
return InChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr unsigned ToDigit(CharType InChar)
|
NODISCARD FORCEINLINE static constexpr unsigned ToDigit(FCharType InChar)
|
||||||
{
|
{
|
||||||
static_assert(TChar::IsASCII());
|
static_assert(TChar::IsASCII());
|
||||||
|
|
||||||
@ -834,12 +834,12 @@ struct TChar
|
|||||||
|
|
||||||
static_assert(sizeof(DigitFromChar) == 256);
|
static_assert(sizeof(DigitFromChar) == 256);
|
||||||
|
|
||||||
if constexpr (sizeof(CharType) > 1) if (InChar >> 8) return DigitFromChar[0];
|
if constexpr (sizeof(FCharType) > 1) if (InChar >> 8) return DigitFromChar[0];
|
||||||
|
|
||||||
return DigitFromChar[InChar];
|
return DigitFromChar[InChar];
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr unsigned ToDigit(CharType InChar, bool bLowercase)
|
NODISCARD FORCEINLINE static constexpr unsigned ToDigit(FCharType InChar, bool bLowercase)
|
||||||
{
|
{
|
||||||
static_assert(TChar::IsASCII());
|
static_assert(TChar::IsASCII());
|
||||||
|
|
||||||
@ -867,7 +867,7 @@ struct TChar
|
|||||||
|
|
||||||
static_assert(sizeof(DigitFromChar) == 256);
|
static_assert(sizeof(DigitFromChar) == 256);
|
||||||
|
|
||||||
if constexpr (sizeof(CharType) > 1) if (InChar >> 8) return DigitFromChar[0];
|
if constexpr (sizeof(FCharType) > 1) if (InChar >> 8) return DigitFromChar[0];
|
||||||
|
|
||||||
return DigitFromChar[InChar];
|
return DigitFromChar[InChar];
|
||||||
}
|
}
|
||||||
@ -894,25 +894,25 @@ struct TChar
|
|||||||
|
|
||||||
static_assert(sizeof(DigitFromChar) == 256);
|
static_assert(sizeof(DigitFromChar) == 256);
|
||||||
|
|
||||||
if constexpr (sizeof(CharType) > 1) if (InChar >> 8) return DigitFromChar[0];
|
if constexpr (sizeof(FCharType) > 1) if (InChar >> 8) return DigitFromChar[0];
|
||||||
|
|
||||||
return DigitFromChar[InChar];
|
return DigitFromChar[InChar];
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr CharType FromDigit(unsigned InDigit)
|
NODISCARD FORCEINLINE static constexpr FCharType FromDigit(unsigned InDigit)
|
||||||
{
|
{
|
||||||
checkf(InDigit < 36, TEXT("Digit must be in the range [0, 35]."));
|
checkf(InDigit < 36, TEXT("Digit must be in the range [0, 35]."));
|
||||||
|
|
||||||
return LITERAL(CharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit];
|
return LITERAL(FCharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit];
|
||||||
}
|
}
|
||||||
|
|
||||||
NODISCARD FORCEINLINE static constexpr CharType FromDigit(unsigned InDigit, bool bLowercase)
|
NODISCARD FORCEINLINE static constexpr FCharType FromDigit(unsigned InDigit, bool bLowercase)
|
||||||
{
|
{
|
||||||
checkf(InDigit < 36, TEXT("Digit must be in the range [0, 35]."));
|
checkf(InDigit < 36, TEXT("Digit must be in the range [0, 35]."));
|
||||||
|
|
||||||
if (bLowercase) return LITERAL(CharType, "0123456789abcdefghijklmnopqrstuvwxyz")[InDigit];
|
if (bLowercase) return LITERAL(FCharType, "0123456789abcdefghijklmnopqrstuvwxyz")[InDigit];
|
||||||
|
|
||||||
return LITERAL(CharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit];
|
return LITERAL(FCharType, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")[InDigit];
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -264,6 +264,7 @@ struct TStringObjectFormatter
|
|||||||
{
|
{
|
||||||
static bool Do(auto& Result, auto& Object, auto Param)
|
static bool Do(auto& Result, auto& Object, auto Param)
|
||||||
{
|
{
|
||||||
|
// ReSharper disable once CppInconsistentNaming
|
||||||
using U = TRemoveCVRef<decltype(Object)>;
|
using U = TRemoveCVRef<decltype(Object)>;
|
||||||
|
|
||||||
if constexpr (!CConst<TRemoveReference<decltype(Object)>>)
|
if constexpr (!CConst<TRemoveReference<decltype(Object)>>)
|
||||||
@ -1065,9 +1066,9 @@ struct TStringObjectFormatter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using UnsignedU = TMakeUnsigned<U>;
|
using FUnsignedU = TMakeUnsigned<U>;
|
||||||
|
|
||||||
UnsignedU Unsigned = static_cast<UnsignedU>(Object);
|
FUnsignedU Unsigned = static_cast<FUnsignedU>(Object);
|
||||||
|
|
||||||
bool bNegative = false;
|
bool bNegative = false;
|
||||||
|
|
||||||
@ -1077,11 +1078,11 @@ struct TStringObjectFormatter
|
|||||||
{
|
{
|
||||||
bNegative = true;
|
bNegative = true;
|
||||||
|
|
||||||
Unsigned = static_cast<UnsignedU>(-Unsigned);
|
Unsigned = static_cast<FUnsignedU>(-Unsigned);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_t BufferSize = sizeof(UnsignedU) * 8 + 4;
|
constexpr size_t BufferSize = sizeof(FUnsignedU) * 8 + 4;
|
||||||
|
|
||||||
T Buffer[BufferSize];
|
T Buffer[BufferSize];
|
||||||
|
|
||||||
@ -1111,8 +1112,8 @@ struct TStringObjectFormatter
|
|||||||
case 6:
|
case 6:
|
||||||
case 7:
|
case 7:
|
||||||
case 9:
|
case 9:
|
||||||
case 10: do { *--Iter = static_cast<T>('0' + Unsigned % Param.Base); Unsigned = static_cast<UnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
|
case 10: do { *--Iter = static_cast<T>('0' + Unsigned % Param.Base); Unsigned = static_cast<FUnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
|
||||||
default: do { *--Iter = TChar<T>::FromDigit(Unsigned % Param.Base, bLowercase); Unsigned = static_cast<UnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
|
default: do { *--Iter = TChar<T>::FromDigit(Unsigned % Param.Base, bLowercase); Unsigned = static_cast<FUnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1130,12 +1131,12 @@ struct TStringObjectFormatter
|
|||||||
case 6:
|
case 6:
|
||||||
case 7:
|
case 7:
|
||||||
case 9:
|
case 9:
|
||||||
case 10: do { *--Iter = static_cast<T>('0' + Unsigned % Param.Base); Unsigned = static_cast<UnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
|
case 10: do { *--Iter = static_cast<T>('0' + Unsigned % Param.Base); Unsigned = static_cast<FUnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
|
||||||
default: do { *--Iter = TChar<T>::FromDigit(Unsigned % Param.Base); Unsigned = static_cast<UnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
|
default: do { *--Iter = TChar<T>::FromDigit(Unsigned % Param.Base); Unsigned = static_cast<FUnsignedU>(Unsigned / Param.Base); } while (Unsigned != 0); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else do { *--Iter = static_cast<T>('0' + Unsigned % 10); Unsigned = static_cast<UnsignedU>(Unsigned / 10); } while (Unsigned != 0);
|
else do { *--Iter = static_cast<T>('0' + Unsigned % 10); Unsigned = static_cast<FUnsignedU>(Unsigned / 10); } while (Unsigned != 0);
|
||||||
|
|
||||||
T* DigitBegin = Iter;
|
T* DigitBegin = Iter;
|
||||||
|
|
||||||
@ -1144,7 +1145,7 @@ struct TStringObjectFormatter
|
|||||||
{
|
{
|
||||||
const size_t Padding = Param.Padding - (DigitEnd - DigitBegin);
|
const size_t Padding = Param.Padding - (DigitEnd - DigitBegin);
|
||||||
|
|
||||||
if (Param.Padding < sizeof(UnsignedU) * 8) for (size_t Index = 0; Index != Padding; ++Index) *--Iter = LITERAL(T, '0');
|
if (Param.Padding < sizeof(FUnsignedU) * 8) for (size_t Index = 0; Index != Padding; ++Index) *--Iter = LITERAL(T, '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the prefix to the buffer.
|
// Append the prefix to the buffer.
|
||||||
@ -1171,7 +1172,7 @@ struct TStringObjectFormatter
|
|||||||
{
|
{
|
||||||
const size_t Padding = Param.Padding - (DigitEnd - DigitBegin);
|
const size_t Padding = Param.Padding - (DigitEnd - DigitBegin);
|
||||||
|
|
||||||
if (Param.Padding > sizeof(UnsignedU) * 8)
|
if (Param.Padding > sizeof(FUnsignedU) * 8)
|
||||||
{
|
{
|
||||||
Result.Reserve(Result.Num() + (DigitBegin - Iter) + Param.Padding);
|
Result.Reserve(Result.Num() + (DigitBegin - Iter) + Param.Padding);
|
||||||
|
|
||||||
@ -1349,6 +1350,7 @@ struct TStringObjectParser
|
|||||||
{
|
{
|
||||||
static bool Do(auto& View, auto& Object, auto Param)
|
static bool Do(auto& View, auto& Object, auto Param)
|
||||||
{
|
{
|
||||||
|
// ReSharper disable once CppInconsistentNaming
|
||||||
using U = TRemoveCVRef<decltype(Object)>;
|
using U = TRemoveCVRef<decltype(Object)>;
|
||||||
|
|
||||||
if constexpr (CConst<TRemoveReference<decltype(Object)>>)
|
if constexpr (CConst<TRemoveReference<decltype(Object)>>)
|
||||||
@ -2200,17 +2202,17 @@ struct TStringObjectParser
|
|||||||
return TChar<T>::ToDigit(Char);
|
return TChar<T>::ToDigit(Char);
|
||||||
};
|
};
|
||||||
|
|
||||||
using UnsignedU = TMakeUnsigned<U>;
|
using FUnsignedU = TMakeUnsigned<U>;
|
||||||
|
|
||||||
// The limit value that can be stored in an unsigned integer.
|
// The limit value that can be stored in an unsigned integer.
|
||||||
constexpr UnsignedU UnsignedMaximum = static_cast<UnsignedU>(-1);
|
constexpr FUnsignedU UnsignedMaximum = static_cast<FUnsignedU>(-1);
|
||||||
|
|
||||||
// The limit value that can be stored in a signed integer.
|
// The limit value that can be stored in a signed integer.
|
||||||
constexpr U SignedMaximum = static_cast<U>(UnsignedMaximum >> 1);
|
constexpr U SignedMaximum = static_cast<U>(UnsignedMaximum >> 1);
|
||||||
constexpr U SignedMinimum = -static_cast<U>(SignedMaximum) - 1;
|
constexpr U SignedMinimum = -static_cast<U>(SignedMaximum) - 1;
|
||||||
|
|
||||||
UnsignedU LastValue = 0;
|
FUnsignedU LastValue = 0;
|
||||||
UnsignedU Unsigned = 0;
|
FUnsignedU Unsigned = 0;
|
||||||
|
|
||||||
if (TrimmedView.IsEmpty()) return false;
|
if (TrimmedView.IsEmpty()) return false;
|
||||||
|
|
||||||
@ -2223,7 +2225,7 @@ struct TStringObjectParser
|
|||||||
|
|
||||||
TrimmedView.RemovePrefix(1);
|
TrimmedView.RemovePrefix(1);
|
||||||
|
|
||||||
Unsigned = static_cast<UnsignedU>(Digit);
|
Unsigned = static_cast<FUnsignedU>(Digit);
|
||||||
|
|
||||||
while (!TrimmedView.IsEmpty())
|
while (!TrimmedView.IsEmpty())
|
||||||
{
|
{
|
||||||
@ -2235,7 +2237,7 @@ struct TStringObjectParser
|
|||||||
|
|
||||||
LastValue = Unsigned;
|
LastValue = Unsigned;
|
||||||
|
|
||||||
Unsigned = static_cast<UnsignedU>(LastValue * Base + Digit);
|
Unsigned = static_cast<FUnsignedU>(LastValue * Base + Digit);
|
||||||
|
|
||||||
if (Unsigned < LastValue) return false;
|
if (Unsigned < LastValue) return false;
|
||||||
}
|
}
|
||||||
@ -2245,11 +2247,11 @@ struct TStringObjectParser
|
|||||||
if constexpr (CSigned<U>)
|
if constexpr (CSigned<U>)
|
||||||
{
|
{
|
||||||
// Handle overflow.
|
// Handle overflow.
|
||||||
if (!bNegative && Unsigned >= static_cast<UnsignedU>(SignedMaximum)) return false;
|
if (!bNegative && Unsigned >= static_cast<FUnsignedU>(SignedMaximum)) return false;
|
||||||
if ( bNegative && Unsigned >= static_cast<UnsignedU>(SignedMinimum)) return false;
|
if ( bNegative && Unsigned >= static_cast<FUnsignedU>(SignedMinimum)) return false;
|
||||||
|
|
||||||
// Handle negative sign.
|
// Handle negative sign.
|
||||||
if (bNegative) Unsigned = static_cast<UnsignedU>(-Unsigned);
|
if (bNegative) Unsigned = static_cast<FUnsignedU>(-Unsigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object = static_cast<U>(Unsigned);
|
Object = static_cast<U>(Unsigned);
|
||||||
@ -2705,14 +2707,14 @@ NAMESPACE_PRIVATE_END
|
|||||||
|
|
||||||
template <CCharType T, CAllocator<T> Allocator>
|
template <CCharType T, CAllocator<T> Allocator>
|
||||||
template <typename ... Ts>
|
template <typename ... Ts>
|
||||||
void TString<T, Allocator>::AppendFormat(TStringView<ElementType> Fmt, const Ts&... Args)
|
void TString<T, Allocator>::AppendFormat(TStringView<FElementType> Fmt, const Ts&... Args)
|
||||||
{
|
{
|
||||||
// The Unreal Engine says that the starting buffer size catches 99.97% of printf calls.
|
// The Unreal Engine says that the starting buffer size catches 99.97% of printf calls.
|
||||||
constexpr size_t ReserveBufferSize = 512;
|
constexpr size_t ReserveBufferSize = 512;
|
||||||
|
|
||||||
TString<T, TInlineAllocator<ReserveBufferSize>> Result;
|
TString<T, TInlineAllocator<ReserveBufferSize>> Result;
|
||||||
|
|
||||||
NAMESPACE_PRIVATE::TStringFormatOrParseHelper<ElementType, true>::Do(Result, Fmt, ForwardAsTuple(Args...));
|
NAMESPACE_PRIVATE::TStringFormatOrParseHelper<FElementType, true>::Do(Result, Fmt, ForwardAsTuple(Args...));
|
||||||
|
|
||||||
Append(Result.Begin(), Result.End());
|
Append(Result.Begin(), Result.End());
|
||||||
}
|
}
|
||||||
@ -2721,13 +2723,13 @@ template <CCharType T>
|
|||||||
template <typename ... Ts>
|
template <typename ... Ts>
|
||||||
size_t TStringView<T>::ParseAndTrim(TStringView Fmt, Ts&... Args)
|
size_t TStringView<T>::ParseAndTrim(TStringView Fmt, Ts&... Args)
|
||||||
{
|
{
|
||||||
return NAMESPACE_PRIVATE::TStringFormatOrParseHelper<ElementType, false>::Do(*this, Fmt, ForwardAsTuple(Args...));
|
return NAMESPACE_PRIVATE::TStringFormatOrParseHelper<FElementType, false>::Do(*this, Fmt, ForwardAsTuple(Args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <CCharType T, CAllocator<T> Allocator>
|
template <CCharType T, CAllocator<T> Allocator>
|
||||||
void TString<T, Allocator>::AppendBool(bool Value)
|
void TString<T, Allocator>::AppendBool(bool Value)
|
||||||
{
|
{
|
||||||
NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Invalid);
|
NAMESPACE_PRIVATE::TStringObjectFormatter<FElementType>::Do(*this, AsConst(Value), Invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <CCharType T, CAllocator<T> Allocator>
|
template <CCharType T, CAllocator<T> Allocator>
|
||||||
@ -2738,13 +2740,13 @@ void TString<T, Allocator>::AppendInt(U Value, unsigned Base)
|
|||||||
|
|
||||||
struct { unsigned Base; } Param = { Base };
|
struct { unsigned Base; } Param = { Base };
|
||||||
|
|
||||||
NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Param);
|
NAMESPACE_PRIVATE::TStringObjectFormatter<FElementType>::Do(*this, AsConst(Value), Param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <CCharType T, CAllocator<T> Allocator> template <CFloatingPoint U> requires (!CConst<U> && !CVolatile<U>)
|
template <CCharType T, CAllocator<T> Allocator> template <CFloatingPoint U> requires (!CConst<U> && !CVolatile<U>)
|
||||||
void TString<T, Allocator>::AppendFloat(U Value)
|
void TString<T, Allocator>::AppendFloat(U Value)
|
||||||
{
|
{
|
||||||
NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Invalid);
|
NAMESPACE_PRIVATE::TStringObjectFormatter<FElementType>::Do(*this, AsConst(Value), Invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <CCharType T, CAllocator<T> Allocator> template <CFloatingPoint U> requires (!CConst<U> && !CVolatile<U>)
|
template <CCharType T, CAllocator<T> Allocator> template <CFloatingPoint U> requires (!CConst<U> && !CVolatile<U>)
|
||||||
@ -2752,7 +2754,7 @@ void TString<T, Allocator>::AppendFloat(U Value, bool bFixed, bool bScientific)
|
|||||||
{
|
{
|
||||||
struct { bool bFixed; bool bScientific; } Param = { bFixed, bScientific };
|
struct { bool bFixed; bool bScientific; } Param = { bFixed, bScientific };
|
||||||
|
|
||||||
NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Param);
|
NAMESPACE_PRIVATE::TStringObjectFormatter<FElementType>::Do(*this, AsConst(Value), Param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <CCharType T, CAllocator<T> Allocator> template <CFloatingPoint U> requires (!CConst<U> && !CVolatile<U>)
|
template <CCharType T, CAllocator<T> Allocator> template <CFloatingPoint U> requires (!CConst<U> && !CVolatile<U>)
|
||||||
@ -2760,7 +2762,7 @@ void TString<T, Allocator>::AppendFloat(U Value, bool bFixed, bool bScientific,
|
|||||||
{
|
{
|
||||||
struct { bool bFixed; bool bScientific; unsigned Precision; } Param = { bFixed, bScientific, Precision };
|
struct { bool bFixed; bool bScientific; unsigned Precision; } Param = { bFixed, bScientific, Precision };
|
||||||
|
|
||||||
NAMESPACE_PRIVATE::TStringObjectFormatter<ElementType>::Do(*this, AsConst(Value), Param);
|
NAMESPACE_PRIVATE::TStringObjectFormatter<FElementType>::Do(*this, AsConst(Value), Param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <CCharType T>
|
template <CCharType T>
|
||||||
@ -2768,9 +2770,9 @@ constexpr bool TStringView<T>::ToBoolAndTrim()
|
|||||||
{
|
{
|
||||||
bool Value = false;
|
bool Value = false;
|
||||||
|
|
||||||
if (!NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, Value, Invalid))
|
if (!NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, Value, Invalid))
|
||||||
{
|
{
|
||||||
if (int IntValue; NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, IntValue, Invalid))
|
if (int IntValue; NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, IntValue, Invalid))
|
||||||
{
|
{
|
||||||
Value = IntValue != 0;
|
Value = IntValue != 0;
|
||||||
}
|
}
|
||||||
@ -2789,7 +2791,7 @@ constexpr U TStringView<T>::ToIntAndTrim(unsigned Base)
|
|||||||
|
|
||||||
struct { unsigned Base; } Param = { Base };
|
struct { unsigned Base; } Param = { Base };
|
||||||
|
|
||||||
NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, Value, Param);
|
NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, Value, Param);
|
||||||
|
|
||||||
return Value;
|
return Value;
|
||||||
}
|
}
|
||||||
@ -2802,7 +2804,7 @@ constexpr U TStringView<T>::ToFloatAndTrim(bool bFixed, bool bScientific)
|
|||||||
|
|
||||||
struct { bool bFixed; bool bScientific; } Param = { bFixed, bScientific };
|
struct { bool bFixed; bool bScientific; } Param = { bFixed, bScientific };
|
||||||
|
|
||||||
NAMESPACE_PRIVATE::TStringObjectParser<ElementType>::Do(*this, Value, Param);
|
NAMESPACE_PRIVATE::TStringObjectParser<FElementType>::Do(*this, Value, Param);
|
||||||
|
|
||||||
return Value;
|
return Value;
|
||||||
}
|
}
|
||||||
|
@ -35,33 +35,33 @@ class TString : public TArray<T, Allocator>
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Super = TArray<T, Allocator>;
|
using FSuper = TArray<T, Allocator>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = typename Super::ElementType;
|
using FElementType = typename FSuper::FElementType;
|
||||||
using AllocatorType = typename Super::AllocatorType;
|
using FAllocatorType = typename FSuper::FAllocatorType;
|
||||||
|
|
||||||
using Reference = typename Super:: Reference;
|
using FReference = typename FSuper:: FReference;
|
||||||
using ConstReference = typename Super::ConstReference;
|
using FConstReference = typename FSuper::FConstReference;
|
||||||
|
|
||||||
using Iterator = typename Super:: Iterator;
|
using FIterator = typename FSuper:: FIterator;
|
||||||
using ConstIterator = typename Super::ConstIterator;
|
using FConstIterator = typename FSuper::FConstIterator;
|
||||||
|
|
||||||
using ReverseIterator = typename Super:: ReverseIterator;
|
using FReverseIterator = typename FSuper:: FReverseIterator;
|
||||||
using ConstReverseIterator = typename Super::ConstReverseIterator;
|
using FConstReverseIterator = typename FSuper::FConstReverseIterator;
|
||||||
|
|
||||||
static_assert(CContiguousIterator< Iterator>);
|
static_assert(CContiguousIterator< FIterator>);
|
||||||
static_assert(CContiguousIterator<ConstIterator>);
|
static_assert(CContiguousIterator<FConstIterator>);
|
||||||
|
|
||||||
/** Default constructor. Constructs an empty string. */
|
/** Default constructor. Constructs an empty string. */
|
||||||
FORCEINLINE TString() = default;
|
FORCEINLINE TString() = default;
|
||||||
|
|
||||||
/** Constructs the string with 'Count' copies of characters with 'InValue'. */
|
/** Constructs the string with 'Count' copies of characters with 'InValue'. */
|
||||||
FORCEINLINE TString(size_t Count, ElementType InChar) : Super(Count, InChar) { }
|
FORCEINLINE TString(size_t Count, FElementType InChar) : FSuper(Count, InChar) { }
|
||||||
|
|
||||||
/** Constructs a string with the contents of the range ['InPtr', 'InPtr' + 'Count'). */
|
/** Constructs a string with the contents of the range ['InPtr', 'InPtr' + 'Count'). */
|
||||||
FORCEINLINE TString(const ElementType* InPtr, size_t Count) : TString(TStringView<ElementType>(InPtr, Count))
|
FORCEINLINE TString(const FElementType* InPtr, size_t Count) : TString(TStringView<FElementType>(InPtr, Count))
|
||||||
{
|
{
|
||||||
checkf(InPtr != nullptr, TEXT("TString cannot be initialized by nullptr. Please check the pointer."));
|
checkf(InPtr != nullptr, TEXT("TString cannot be initialized by nullptr. Please check the pointer."));
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ public:
|
|||||||
FORCEINLINE TString(nullptr_t, size_t) = delete;
|
FORCEINLINE TString(nullptr_t, size_t) = delete;
|
||||||
|
|
||||||
/** Constructs a string with the contents of the range ['InPtr', '\0'). */
|
/** Constructs a string with the contents of the range ['InPtr', '\0'). */
|
||||||
FORCEINLINE TString(const ElementType* InPtr) : TString(TStringView<ElementType>(InPtr))
|
FORCEINLINE TString(const FElementType* InPtr) : TString(TStringView<FElementType>(InPtr))
|
||||||
{
|
{
|
||||||
checkf(InPtr != nullptr, TEXT("TString cannot be initialized by nullptr. Please check the pointer."));
|
checkf(InPtr != nullptr, TEXT("TString cannot be initialized by nullptr. Please check the pointer."));
|
||||||
}
|
}
|
||||||
@ -77,11 +77,11 @@ public:
|
|||||||
FORCEINLINE TString(nullptr_t) = delete;
|
FORCEINLINE TString(nullptr_t) = delete;
|
||||||
|
|
||||||
/** Constructs the string with the contents of the 'View'. */
|
/** Constructs the string with the contents of the 'View'. */
|
||||||
FORCEINLINE TString(TStringView<ElementType> View) : TString(View.Begin(), View.End()) { }
|
FORCEINLINE TString(TStringView<FElementType> View) : TString(View.Begin(), View.End()) { }
|
||||||
|
|
||||||
/** Constructs the string with the contents of the range ['First', 'Last'). */
|
/** Constructs the string with the contents of the range ['First', 'Last'). */
|
||||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
|
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
|
||||||
FORCEINLINE TString(I First, S Last) : Super(MoveTemp(First), MoveTemp(Last)) { }
|
FORCEINLINE TString(I First, S Last) : FSuper(MoveTemp(First), MoveTemp(Last)) { }
|
||||||
|
|
||||||
/** Copy constructor. Constructs the string with the copy of the contents of 'InValue'. */
|
/** Copy constructor. Constructs the string with the copy of the contents of 'InValue'. */
|
||||||
FORCEINLINE TString(const TString&) = default;
|
FORCEINLINE TString(const TString&) = default;
|
||||||
@ -90,7 +90,7 @@ public:
|
|||||||
FORCEINLINE TString(TString&&) = default;
|
FORCEINLINE TString(TString&&) = default;
|
||||||
|
|
||||||
/** Constructs the string with the contents of the initializer list. */
|
/** Constructs the string with the contents of the initializer list. */
|
||||||
FORCEINLINE TString(initializer_list<ElementType> IL) : TString(Iteration::Begin(IL), Iteration::End(IL)) { }
|
FORCEINLINE TString(initializer_list<FElementType> IL) : TString(Iteration::Begin(IL), Iteration::End(IL)) { }
|
||||||
|
|
||||||
/** Copy assignment operator. Replaces the contents with a copy of the contents of 'InValue'. */
|
/** Copy assignment operator. Replaces the contents with a copy of the contents of 'InValue'. */
|
||||||
FORCEINLINE TString& operator=(const TString&) = default;
|
FORCEINLINE TString& operator=(const TString&) = default;
|
||||||
@ -99,27 +99,27 @@ public:
|
|||||||
FORCEINLINE TString& operator=(TString&&) = default;
|
FORCEINLINE TString& operator=(TString&&) = default;
|
||||||
|
|
||||||
/** Compares the contents of two strings. */
|
/** Compares the contents of two strings. */
|
||||||
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, const TString& RHS) { return TStringView<ElementType>(LHS) == TStringView<ElementType>(RHS); }
|
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, const TString& RHS) { return TStringView<FElementType>(LHS) == TStringView<FElementType>(RHS); }
|
||||||
|
|
||||||
/** Compares the contents of a string and a character. */
|
/** Compares the contents of a string and a character. */
|
||||||
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, ElementType RHS) { return TStringView<ElementType>(LHS) == RHS; }
|
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, FElementType RHS) { return TStringView<FElementType>(LHS) == RHS; }
|
||||||
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, const ElementType* RHS) { return TStringView<ElementType>(LHS) == RHS; }
|
NODISCARD friend FORCEINLINE bool operator==(const TString& LHS, const FElementType* RHS) { return TStringView<FElementType>(LHS) == RHS; }
|
||||||
NODISCARD friend FORCEINLINE bool operator==( ElementType LHS, const TString& RHS) { return LHS == TStringView<ElementType>(RHS); }
|
NODISCARD friend FORCEINLINE bool operator==( FElementType LHS, const TString& RHS) { return LHS == TStringView<FElementType>(RHS); }
|
||||||
NODISCARD friend FORCEINLINE bool operator==(const ElementType* LHS, const TString& RHS) { return LHS == TStringView<ElementType>(RHS); }
|
NODISCARD friend FORCEINLINE bool operator==(const FElementType* LHS, const TString& RHS) { return LHS == TStringView<FElementType>(RHS); }
|
||||||
|
|
||||||
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
||||||
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, const TString& RHS) { return TStringView<ElementType>(LHS) <=> TStringView<ElementType>(RHS); }
|
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, const TString& RHS) { return TStringView<FElementType>(LHS) <=> TStringView<FElementType>(RHS); }
|
||||||
|
|
||||||
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
/** Compares the contents of 'LHS' and 'RHS' lexicographically. */
|
||||||
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, ElementType RHS) { return TStringView<ElementType>(LHS) <=> RHS; }
|
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, FElementType RHS) { return TStringView<FElementType>(LHS) <=> RHS; }
|
||||||
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, const ElementType* RHS) { return TStringView<ElementType>(LHS) <=> RHS; }
|
NODISCARD friend FORCEINLINE auto operator<=>(const TString& LHS, const FElementType* RHS) { return TStringView<FElementType>(LHS) <=> RHS; }
|
||||||
NODISCARD friend FORCEINLINE auto operator<=>( ElementType LHS, const TString& RHS) { return LHS <=> TStringView<ElementType>(RHS); }
|
NODISCARD friend FORCEINLINE auto operator<=>( FElementType LHS, const TString& RHS) { return LHS <=> TStringView<FElementType>(RHS); }
|
||||||
NODISCARD friend FORCEINLINE auto operator<=>(const ElementType* LHS, const TString& RHS) { return LHS <=> TStringView<ElementType>(RHS); }
|
NODISCARD friend FORCEINLINE auto operator<=>(const FElementType* LHS, const TString& RHS) { return LHS <=> TStringView<FElementType>(RHS); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Inserts 'InValue' before 'Index' in the string. */
|
/** Inserts 'InValue' before 'Index' in the string. */
|
||||||
FORCEINLINE Iterator Insert(size_t Index, ElementType InValue)
|
FORCEINLINE FIterator Insert(size_t Index, FElementType InValue)
|
||||||
{
|
{
|
||||||
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
|
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
|
||||||
|
|
||||||
@ -127,15 +127,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts 'InValue' before 'Iter' in the string. */
|
/** Inserts 'InValue' before 'Iter' in the string. */
|
||||||
FORCEINLINE Iterator Insert(ConstIterator Iter, ElementType InValue)
|
FORCEINLINE FIterator Insert(FConstIterator Iter, FElementType InValue)
|
||||||
{
|
{
|
||||||
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
return Super::Insert(Iter, InValue);
|
return FSuper::Insert(Iter, InValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts 'Count' copies of the 'InValue' before 'Index' in the string. */
|
/** Inserts 'Count' copies of the 'InValue' before 'Index' in the string. */
|
||||||
FORCEINLINE Iterator Insert(size_t Index, size_t Count, ElementType InValue)
|
FORCEINLINE FIterator Insert(size_t Index, size_t Count, FElementType InValue)
|
||||||
{
|
{
|
||||||
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
|
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
|
||||||
|
|
||||||
@ -143,15 +143,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts 'Count' copies of the 'InValue' before 'Iter' in the string. */
|
/** Inserts 'Count' copies of the 'InValue' before 'Iter' in the string. */
|
||||||
FORCEINLINE Iterator Insert(ConstIterator Iter, size_t Count, ElementType InValue)
|
FORCEINLINE FIterator Insert(FConstIterator Iter, size_t Count, FElementType InValue)
|
||||||
{
|
{
|
||||||
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
return Super::Insert(Iter, Count, InValue);
|
return FSuper::Insert(Iter, Count, InValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts characters from the 'View' before 'Index' in the string. */
|
/** Inserts characters from the 'View' before 'Index' in the string. */
|
||||||
FORCEINLINE Iterator Insert(size_t Index, TStringView<ElementType> View)
|
FORCEINLINE FIterator Insert(size_t Index, TStringView<FElementType> View)
|
||||||
{
|
{
|
||||||
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
|
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts characters from the 'View' before 'Iter' in the string. */
|
/** Inserts characters from the 'View' before 'Iter' in the string. */
|
||||||
FORCEINLINE Iterator Insert(ConstIterator Iter, TStringView<ElementType> View)
|
FORCEINLINE FIterator Insert(FConstIterator Iter, TStringView<FElementType> View)
|
||||||
{
|
{
|
||||||
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -167,8 +167,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts characters from the range ['First', 'Last') before 'Index' in the string. */
|
/** Inserts characters from the range ['First', 'Last') before 'Index' in the string. */
|
||||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
|
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
|
||||||
FORCEINLINE Iterator Insert(size_t Index, I First, S Last)
|
FORCEINLINE FIterator Insert(size_t Index, I First, S Last)
|
||||||
{
|
{
|
||||||
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
|
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
|
||||||
|
|
||||||
@ -176,16 +176,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts characters from the range ['First', 'Last') before 'Iter'. */
|
/** Inserts characters from the range ['First', 'Last') before 'Iter'. */
|
||||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
|
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
|
||||||
FORCEINLINE Iterator Insert(ConstIterator Iter, I First, S Last)
|
FORCEINLINE FIterator Insert(FConstIterator Iter, I First, S Last)
|
||||||
{
|
{
|
||||||
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
return Super::Insert(Iter, MoveTemp(First), MoveTemp(Last));
|
return FSuper::Insert(Iter, MoveTemp(First), MoveTemp(Last));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts characters from the initializer list before 'Index' in the string. */
|
/** Inserts characters from the initializer list before 'Index' in the string. */
|
||||||
FORCEINLINE Iterator Insert(size_t Index, initializer_list<ElementType> IL)
|
FORCEINLINE FIterator Insert(size_t Index, initializer_list<FElementType> IL)
|
||||||
{
|
{
|
||||||
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
|
checkf(Index <= this->Num(), TEXT("Illegal index. Please check Index <= Num()."));
|
||||||
|
|
||||||
@ -193,15 +193,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Inserts characters from the initializer list before 'Iter' in the string. */
|
/** Inserts characters from the initializer list before 'Iter' in the string. */
|
||||||
FORCEINLINE Iterator Insert(ConstIterator Iter, initializer_list<ElementType> IL)
|
FORCEINLINE FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL)
|
||||||
{
|
{
|
||||||
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(this->IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
return Super::Insert(Iter, IL);
|
return FSuper::Insert(Iter, IL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Erases the character at 'Index' in the string. But it may change the order of characters. */
|
/** Erases the character at 'Index' in the string. But it may change the order of characters. */
|
||||||
FORCEINLINE Iterator Erase(size_t Index, bool bAllowShrinking = true)
|
FORCEINLINE FIterator Erase(size_t Index, bool bAllowShrinking = true)
|
||||||
{
|
{
|
||||||
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index < Num()."));
|
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index < Num()."));
|
||||||
|
|
||||||
@ -209,15 +209,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Erases the character at 'Iter' in the string. But it may change the order of characters. */
|
/** Erases the character at 'Iter' in the string. But it may change the order of characters. */
|
||||||
FORCEINLINE Iterator Erase(ConstIterator Iter, bool bAllowShrinking = true)
|
FORCEINLINE FIterator Erase(FConstIterator Iter, bool bAllowShrinking = true)
|
||||||
{
|
{
|
||||||
checkf(this->IsValidIterator(Iter) && Iter != this->End(), TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(this->IsValidIterator(Iter) && Iter != this->End(), TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
return Super::StableErase(Iter, bAllowShrinking);
|
return FSuper::StableErase(Iter, bAllowShrinking);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Erases 'CountToErase' characters starting from 'Index' in the string. But it may change the order of characters. */
|
/** Erases 'CountToErase' characters starting from 'Index' in the string. But it may change the order of characters. */
|
||||||
FORCEINLINE Iterator Erase(size_t Index, size_t CountToErase, bool bAllowShrinking = true)
|
FORCEINLINE FIterator Erase(size_t Index, size_t CountToErase, bool bAllowShrinking = true)
|
||||||
{
|
{
|
||||||
checkf(Index <= this->Num() && Index + CountToErase <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToErase."));
|
checkf(Index <= this->Num() && Index + CountToErase <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToErase."));
|
||||||
|
|
||||||
@ -226,24 +226,24 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Erases the characters in the range ['First', 'Last') in the string. But it may change the order of characters. */
|
/** Erases the characters in the range ['First', 'Last') in the string. But it may change the order of characters. */
|
||||||
FORCEINLINE Iterator Erase(ConstIterator First, ConstIterator Last, bool bAllowShrinking = true)
|
FORCEINLINE FIterator Erase(FConstIterator First, FConstIterator Last, bool bAllowShrinking = true)
|
||||||
{
|
{
|
||||||
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
return Super::StableErase(First, Last, bAllowShrinking);
|
return FSuper::StableErase(First, Last, bAllowShrinking);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Here, the 'Erase' is already stable and there is no need to provide 'StableErase'. */
|
/** Here, the 'Erase' is already stable and there is no need to provide 'StableErase'. */
|
||||||
void StableErase(...) = delete;
|
void StableErase(...) = delete;
|
||||||
|
|
||||||
/** Appends 'Count' copies of the 'InValue' to the end of the string. */
|
/** Appends 'Count' copies of the 'InValue' to the end of the string. */
|
||||||
TString& Append(size_t Count, ElementType InChar) { return Append(MakeCountedConstantIterator(InChar, Count), DefaultSentinel); }
|
TString& Append(size_t Count, FElementType InChar) { return Append(MakeCountedConstantIterator(InChar, Count), DefaultSentinel); }
|
||||||
|
|
||||||
/** Appends the contents of the 'View' to the end of the string. */
|
/** Appends the contents of the 'View' to the end of the string. */
|
||||||
FORCEINLINE TString& Append(TStringView<ElementType> View) { return Append(View.Begin(), View.End()); }
|
FORCEINLINE TString& Append(TStringView<FElementType> View) { return Append(View.Begin(), View.End()); }
|
||||||
|
|
||||||
/** Appends the contents of the range ['First', 'Last') to the end of the string. */
|
/** Appends the contents of the range ['First', 'Last') to the end of the string. */
|
||||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
|
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
|
||||||
TString& Append(I First, S Last)
|
TString& Append(I First, S Last)
|
||||||
{
|
{
|
||||||
if constexpr (CForwardIterator<I>)
|
if constexpr (CForwardIterator<I>)
|
||||||
@ -258,7 +258,7 @@ public:
|
|||||||
|
|
||||||
for (size_t Index = CurrentNum; Index != CurrentNum + Count; ++Index)
|
for (size_t Index = CurrentNum; Index != CurrentNum + Count; ++Index)
|
||||||
{
|
{
|
||||||
(*this)[Index] = ElementType(*First++);
|
(*this)[Index] = FElementType(*First++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -270,40 +270,40 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Appends the contents of the initializer list to the end of the string. */
|
/** Appends the contents of the initializer list to the end of the string. */
|
||||||
FORCEINLINE TString& Append(initializer_list<ElementType> IL) { return Append(Iteration::Begin(IL), Iteration::End(IL)); }
|
FORCEINLINE TString& Append(initializer_list<FElementType> IL) { return Append(Iteration::Begin(IL), Iteration::End(IL)); }
|
||||||
|
|
||||||
/** Appends the given character value to the end of the string. */
|
/** Appends the given character value to the end of the string. */
|
||||||
FORCEINLINE TString& operator+=(ElementType InChar) { return Append(1, InChar); }
|
FORCEINLINE TString& operator+=(FElementType InChar) { return Append(1, InChar); }
|
||||||
|
|
||||||
/** Appends the contents of the 'View' to the end of the string. */
|
/** Appends the contents of the 'View' to the end of the string. */
|
||||||
FORCEINLINE TString& operator+=(TStringView<ElementType> View) { return Append(View); }
|
FORCEINLINE TString& operator+=(TStringView<FElementType> View) { return Append(View); }
|
||||||
|
|
||||||
/** Appends the contents of the range ['First', 'Last') to the end of the string. */
|
/** Appends the contents of the range ['First', 'Last') to the end of the string. */
|
||||||
FORCEINLINE TString& operator+=(initializer_list<ElementType> IL) { return Append(IL); }
|
FORCEINLINE TString& operator+=(initializer_list<FElementType> IL) { return Append(IL); }
|
||||||
|
|
||||||
/** Concatenates two strings. */
|
/** Concatenates two strings. */
|
||||||
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, const TString& RHS) { return TString(LHS).Append(RHS); }
|
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, const TString& RHS) { return TString(LHS).Append(RHS); }
|
||||||
|
|
||||||
/** Concatenates the string with the given character value. */
|
/** Concatenates the string with the given character value. */
|
||||||
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, ElementType RHS) { return TString(LHS).Append(1, RHS); }
|
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, FElementType RHS) { return TString(LHS).Append(1, RHS); }
|
||||||
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, const ElementType* RHS) { return TString(LHS).Append( RHS); }
|
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, const FElementType* RHS) { return TString(LHS).Append( RHS); }
|
||||||
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, TStringView<ElementType> RHS) { return TString(LHS).Append( RHS); }
|
NODISCARD friend FORCEINLINE TString operator+(const TString& LHS, TStringView<FElementType> RHS) { return TString(LHS).Append( RHS); }
|
||||||
NODISCARD friend FORCEINLINE TString operator+( ElementType LHS, const TString& RHS) { return TString(1, LHS).Append(RHS); }
|
NODISCARD friend FORCEINLINE TString operator+( FElementType LHS, const TString& RHS) { return TString(1, LHS).Append(RHS); }
|
||||||
NODISCARD friend FORCEINLINE TString operator+( const ElementType* LHS, const TString& RHS) { return TString( LHS).Append(RHS); }
|
NODISCARD friend FORCEINLINE TString operator+( const FElementType* LHS, const TString& RHS) { return TString( LHS).Append(RHS); }
|
||||||
NODISCARD friend FORCEINLINE TString operator+(TStringView<ElementType> LHS, const TString& RHS) { return TString( LHS).Append(RHS); }
|
NODISCARD friend FORCEINLINE TString operator+(TStringView<FElementType> LHS, const TString& RHS) { return TString( LHS).Append(RHS); }
|
||||||
|
|
||||||
/** Concatenates two strings. The rvalue maybe modified. */
|
/** Concatenates two strings. The rvalue maybe modified. */
|
||||||
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, TString&& RHS) { LHS.Append(MoveTemp(RHS)); return LHS; }
|
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, TString&& RHS) { LHS.Append(MoveTemp(RHS)); return LHS; }
|
||||||
|
|
||||||
/** Concatenates two strings. The rvalue maybe modified. */
|
/** Concatenates two strings. The rvalue maybe modified. */
|
||||||
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, ElementType RHS) { LHS.Append(1, RHS); return LHS; }
|
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, FElementType RHS) { LHS.Append(1, RHS); return LHS; }
|
||||||
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, const ElementType* RHS) { LHS.Append( RHS); return LHS; }
|
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, const FElementType* RHS) { LHS.Append( RHS); return LHS; }
|
||||||
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, TStringView<ElementType> RHS) { LHS.Append( RHS); return LHS; }
|
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, TStringView<FElementType> RHS) { LHS.Append( RHS); return LHS; }
|
||||||
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, const TString<ElementType>& RHS) { LHS.Append( RHS); return LHS; }
|
NODISCARD friend FORCEINLINE TString operator+(TString&& LHS, const TString<FElementType>& RHS) { LHS.Append( RHS); return LHS; }
|
||||||
NODISCARD friend FORCEINLINE TString operator+( ElementType LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
|
NODISCARD friend FORCEINLINE TString operator+( FElementType LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
|
||||||
NODISCARD friend FORCEINLINE TString operator+( const ElementType* LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
|
NODISCARD friend FORCEINLINE TString operator+( const FElementType* LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
|
||||||
NODISCARD friend FORCEINLINE TString operator+( TStringView<ElementType> LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
|
NODISCARD friend FORCEINLINE TString operator+( TStringView<FElementType> LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
|
||||||
NODISCARD friend FORCEINLINE TString operator+(const TString<ElementType>& LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
|
NODISCARD friend FORCEINLINE TString operator+(const TString<FElementType>& LHS, TString&& RHS) { RHS.Insert(0, LHS); return RHS; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -330,7 +330,7 @@ public:
|
|||||||
/** Removes whitespace characters from the start of this string. */
|
/** Removes whitespace characters from the start of this string. */
|
||||||
FORCEINLINE constexpr TString& TrimStart(bool bAllowShrinking = true)
|
FORCEINLINE constexpr TString& TrimStart(bool bAllowShrinking = true)
|
||||||
{
|
{
|
||||||
auto Index = Find([](ElementType Char) { return !TChar<ElementType>::IsSpace(Char); });
|
auto Index = Find([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); });
|
||||||
|
|
||||||
if (Index != INDEX_NONE)
|
if (Index != INDEX_NONE)
|
||||||
{
|
{
|
||||||
@ -344,7 +344,7 @@ public:
|
|||||||
/** Removes whitespace characters from the end of this string. */
|
/** Removes whitespace characters from the end of this string. */
|
||||||
FORCEINLINE constexpr TString& TrimEnd(bool bAllowShrinking = true)
|
FORCEINLINE constexpr TString& TrimEnd(bool bAllowShrinking = true)
|
||||||
{
|
{
|
||||||
auto Index = RFind([](ElementType Char) { return !TChar<ElementType>::IsSpace(Char); });
|
auto Index = RFind([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); });
|
||||||
|
|
||||||
if (Index != INDEX_NONE)
|
if (Index != INDEX_NONE)
|
||||||
{
|
{
|
||||||
@ -367,7 +367,7 @@ public:
|
|||||||
/** Removes characters after the first null-terminator. */
|
/** Removes characters after the first null-terminator. */
|
||||||
FORCEINLINE constexpr TString& TrimToNullTerminator(bool bAllowShrinking = true)
|
FORCEINLINE constexpr TString& TrimToNullTerminator(bool bAllowShrinking = true)
|
||||||
{
|
{
|
||||||
auto Index = Find(LITERAL(ElementType, '\0'));
|
auto Index = Find(LITERAL(FElementType, '\0'));
|
||||||
|
|
||||||
if (Index != INDEX_NONE)
|
if (Index != INDEX_NONE)
|
||||||
{
|
{
|
||||||
@ -380,50 +380,50 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/** @return true if the string view starts with the given prefix, false otherwise. */
|
/** @return true if the string view starts with the given prefix, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool StartsWith(TStringView<ElementType> Prefix) const
|
NODISCARD FORCEINLINE bool StartsWith(TStringView<FElementType> Prefix) const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).StartsWith(Prefix);
|
return TStringView<FElementType>(*this).StartsWith(Prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string view starts with the given prefix, false otherwise. */
|
/** @return true if the string view starts with the given prefix, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool StartsWith(ElementType Prefix) const
|
NODISCARD FORCEINLINE bool StartsWith(FElementType Prefix) const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).StartsWith(Prefix);
|
return TStringView<FElementType>(*this).StartsWith(Prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string view ends with the given suffix, false otherwise. */
|
/** @return true if the string view ends with the given suffix, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool EndsWith(TStringView<ElementType> Suffix) const
|
NODISCARD FORCEINLINE bool EndsWith(TStringView<FElementType> Suffix) const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).EndsWith(Suffix);
|
return TStringView<FElementType>(*this).EndsWith(Suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string view ends with the given suffix, false otherwise. */
|
/** @return true if the string view ends with the given suffix, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool EndsWith(ElementType Suffix) const
|
NODISCARD FORCEINLINE bool EndsWith(FElementType Suffix) const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).EndsWith(Suffix);
|
return TStringView<FElementType>(*this).EndsWith(Suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string view contains the given substring, false otherwise. */
|
/** @return true if the string view contains the given substring, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool Contains(TStringView<ElementType> View) const
|
NODISCARD FORCEINLINE bool Contains(TStringView<FElementType> View) const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).Contains(View);
|
return TStringView<FElementType>(*this).Contains(View);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string view contains the given character, false otherwise. */
|
/** @return true if the string view contains the given character, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool Contains(ElementType Char) const
|
NODISCARD FORCEINLINE bool Contains(FElementType Char) const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).Contains(Char);
|
return TStringView<FElementType>(*this).Contains(Char);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string view contains character that satisfy the given predicate, false otherwise. */
|
/** @return true if the string view contains character that satisfy the given predicate, false otherwise. */
|
||||||
template <CPredicate<ElementType> F>
|
template <CPredicate<FElementType> F>
|
||||||
NODISCARD FORCEINLINE bool Contains(F&& InPredicate) const
|
NODISCARD FORCEINLINE bool Contains(F&& InPredicate) const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).Contains(Forward<F>(InPredicate));
|
return TStringView<FElementType>(*this).Contains(Forward<F>(InPredicate));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Replace the substring [Index, Index + CountToReplace) with 'Count' copies of the 'InChar'. */
|
/** Replace the substring [Index, Index + CountToReplace) with 'Count' copies of the 'InChar'. */
|
||||||
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, size_t Count, ElementType InChar)
|
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, size_t Count, FElementType InChar)
|
||||||
{
|
{
|
||||||
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
|
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
|
||||||
|
|
||||||
@ -431,7 +431,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Replace the substring ['First', 'Last') with 'Count' copies of the 'InChar'. */
|
/** Replace the substring ['First', 'Last') with 'Count' copies of the 'InChar'. */
|
||||||
FORCEINLINE TString& Replace(ConstIterator First, ConstIterator Last, size_t Count, ElementType InChar)
|
FORCEINLINE TString& Replace(FConstIterator First, FConstIterator Last, size_t Count, FElementType InChar)
|
||||||
{
|
{
|
||||||
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -439,7 +439,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Replace the substring [Index, Index + CountToReplace) with the contents of the 'View'. */
|
/** Replace the substring [Index, Index + CountToReplace) with the contents of the 'View'. */
|
||||||
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, TStringView<ElementType> View)
|
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, TStringView<FElementType> View)
|
||||||
{
|
{
|
||||||
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
|
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
|
||||||
|
|
||||||
@ -447,7 +447,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Replace the substring ['First', 'Last') with the contents of the 'View'. */
|
/** Replace the substring ['First', 'Last') with the contents of the 'View'. */
|
||||||
FORCEINLINE TString& Replace(ConstIterator First, ConstIterator Last, TStringView<ElementType> View)
|
FORCEINLINE TString& Replace(FConstIterator First, FConstIterator Last, TStringView<FElementType> View)
|
||||||
{
|
{
|
||||||
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -455,7 +455,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Replace the substring [Index, Index + CountToReplace) with the contents of the range ['First', 'Last'). */
|
/** Replace the substring [Index, Index + CountToReplace) with the contents of the range ['First', 'Last'). */
|
||||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
|
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
|
||||||
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, I InString, S Sentinel)
|
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, I InString, S Sentinel)
|
||||||
{
|
{
|
||||||
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
|
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
|
||||||
@ -464,8 +464,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Replace the substring ['First', 'Last') with the contents of the range ['InString', 'Sentinel'). */
|
/** Replace the substring ['First', 'Last') with the contents of the range ['InString', 'Sentinel'). */
|
||||||
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<ElementType, TIteratorReferenceType<I>>)
|
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>)
|
||||||
TString& Replace(ConstIterator First, ConstIterator Last, I InString, S Sentinel)
|
TString& Replace(FConstIterator First, FConstIterator Last, I InString, S Sentinel)
|
||||||
{
|
{
|
||||||
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -484,7 +484,7 @@ public:
|
|||||||
{
|
{
|
||||||
for (size_t Index = InsertIndex; Index != InsertIndex + InsertCount; ++Index)
|
for (size_t Index = InsertIndex; Index != InsertIndex + InsertCount; ++Index)
|
||||||
{
|
{
|
||||||
(*this)[Index] = ElementType(*InString++);
|
(*this)[Index] = FElementType(*InString++);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t Index = InsertIndex + InsertCount; Index != NumToReset; ++Index)
|
for (size_t Index = InsertIndex + InsertCount; Index != NumToReset; ++Index)
|
||||||
@ -505,7 +505,7 @@ public:
|
|||||||
|
|
||||||
for (size_t Index = InsertIndex; Index != InsertIndex + InsertCount; ++Index)
|
for (size_t Index = InsertIndex; Index != InsertIndex + InsertCount; ++Index)
|
||||||
{
|
{
|
||||||
(*this)[Index] = ElementType(*InString++);
|
(*this)[Index] = FElementType(*InString++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -520,7 +520,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Replace the substring [Index, Index + CountToReplace) with the contents of the initializer list. */
|
/** Replace the substring [Index, Index + CountToReplace) with the contents of the initializer list. */
|
||||||
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, initializer_list<ElementType> IL)
|
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, initializer_list<FElementType> IL)
|
||||||
{
|
{
|
||||||
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
|
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
|
||||||
|
|
||||||
@ -528,7 +528,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Replace the substring ['First', 'Last') with the contents of the initializer list. */
|
/** Replace the substring ['First', 'Last') with the contents of the initializer list. */
|
||||||
FORCEINLINE TString& Replace(ConstIterator First, ConstIterator Last, initializer_list<ElementType> IL)
|
FORCEINLINE TString& Replace(FConstIterator First, FConstIterator Last, initializer_list<FElementType> IL)
|
||||||
{
|
{
|
||||||
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
|
||||||
|
|
||||||
@ -540,133 +540,133 @@ public:
|
|||||||
{
|
{
|
||||||
checkf(Offset <= this->Num() && Offset + Count <= this->Num(), TEXT("Illegal substring range. Please check Offset and Count."));
|
checkf(Offset <= this->Num() && Offset + Count <= this->Num(), TEXT("Illegal substring range. Please check Offset and Count."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).Substr(Offset, Count);
|
return TStringView<FElementType>(*this).Substr(Offset, Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Copies the characters of this string to the destination buffer without null-termination. */
|
/** Copies the characters of this string to the destination buffer without null-termination. */
|
||||||
FORCEINLINE size_t Copy(ElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const
|
FORCEINLINE size_t Copy(FElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const
|
||||||
{
|
{
|
||||||
checkf(Dest != nullptr, TEXT("Illegal destination buffer. Please check the pointer."));
|
checkf(Dest != nullptr, TEXT("Illegal destination buffer. Please check the pointer."));
|
||||||
|
|
||||||
checkf(Offset <= this->Num() && (Count == DynamicExtent || Offset + Count <= this->Num()), TEXT("Illegal subview range. Please check Offset and Count."));
|
checkf(Offset <= this->Num() && (Count == DynamicExtent || Offset + Count <= this->Num()), TEXT("Illegal subview range. Please check Offset and Count."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).Copy(Dest, Count, Offset);
|
return TStringView<FElementType>(*this).Copy(Dest, Count, Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE size_t Copy(nullptr_t, size_t = DynamicExtent, size_t = 0) const = delete;
|
FORCEINLINE size_t Copy(nullptr_t, size_t = DynamicExtent, size_t = 0) const = delete;
|
||||||
|
|
||||||
/** @return The index of the first occurrence of the given substring, or INDEX_NONE if not found. */
|
/** @return The index of the first occurrence of the given substring, or INDEX_NONE if not found. */
|
||||||
NODISCARD size_t Find(TStringView<ElementType> View, size_t Index = 0) const
|
NODISCARD size_t Find(TStringView<FElementType> View, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).Find(View, Index);
|
return TStringView<FElementType>(*this).Find(View, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD size_t Find(ElementType Char, size_t Index = 0) const
|
NODISCARD size_t Find(FElementType Char, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).Find(Char, Index);
|
return TStringView<FElementType>(*this).Find(Char, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the first occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
|
/** @return The index of the first occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
|
||||||
template <CPredicate<ElementType> F>
|
template <CPredicate<FElementType> F>
|
||||||
NODISCARD size_t Find(F&& InPredicate, size_t Index = 0) const
|
NODISCARD size_t Find(F&& InPredicate, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).Find(Forward<F>(InPredicate), Index);
|
return TStringView<FElementType>(*this).Find(Forward<F>(InPredicate), Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last occurrence of the given substring, or INDEX_NONE if not found. */
|
/** @return The index of the last occurrence of the given substring, or INDEX_NONE if not found. */
|
||||||
NODISCARD size_t RFind(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
|
NODISCARD size_t RFind(TStringView<FElementType> View, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).RFind(View, Index);
|
return TStringView<FElementType>(*this).RFind(View, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD size_t RFind(ElementType Char, size_t Index = INDEX_NONE) const
|
NODISCARD size_t RFind(FElementType Char, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).RFind(Char, Index);
|
return TStringView<FElementType>(*this).RFind(Char, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
|
/** @return The index of the last occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
|
||||||
template <CPredicate<ElementType> F>
|
template <CPredicate<FElementType> F>
|
||||||
NODISCARD size_t RFind(F&& InPredicate, size_t Index = INDEX_NONE) const
|
NODISCARD size_t RFind(F&& InPredicate, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).RFind(Forward<F>(InPredicate), Index);
|
return TStringView<FElementType>(*this).RFind(Forward<F>(InPredicate), Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the first occurrence of the character contained in the given view, or INDEX_NONE if not found. */
|
/** @return The index of the first occurrence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE size_t FindFirstOf(TStringView<ElementType> View, size_t Index = 0) const
|
NODISCARD FORCEINLINE size_t FindFirstOf(TStringView<FElementType> View, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).FindFirstOf(View, Index);
|
return TStringView<FElementType>(*this).FindFirstOf(View, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE size_t FindFirstOf(ElementType Char, size_t Index = 0) const
|
NODISCARD FORCEINLINE size_t FindFirstOf(FElementType Char, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).FindFirstOf(Char, Index);
|
return TStringView<FElementType>(*this).FindFirstOf(Char, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last occurrence of the character contained in the given view, or INDEX_NONE if not found. */
|
/** @return The index of the last occurrence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE size_t FindLastOf(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
|
NODISCARD FORCEINLINE size_t FindLastOf(TStringView<FElementType> View, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).FindLastOf(View, Index);
|
return TStringView<FElementType>(*this).FindLastOf(View, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE size_t FindLastOf(ElementType Char, size_t Index = INDEX_NONE) const
|
NODISCARD FORCEINLINE size_t FindLastOf(FElementType Char, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).FindLastOf(Char, Index);
|
return TStringView<FElementType>(*this).FindLastOf(Char, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the first absence of the character contained in the given view, or INDEX_NONE if not found. */
|
/** @return The index of the first absence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE size_t FindFirstNotOf(TStringView<ElementType> View, size_t Index = 0) const
|
NODISCARD FORCEINLINE size_t FindFirstNotOf(TStringView<FElementType> View, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).FindFirstNotOf(View, Index);
|
return TStringView<FElementType>(*this).FindFirstNotOf(View, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the first absence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the first absence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE size_t FindFirstNotOf(ElementType Char, size_t Index = 0) const
|
NODISCARD FORCEINLINE size_t FindFirstNotOf(FElementType Char, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).FindFirstNotOf(Char, Index);
|
return TStringView<FElementType>(*this).FindFirstNotOf(Char, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last absence of the character contained in the given view, or INDEX_NONE if not found. */
|
/** @return The index of the last absence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE size_t FindLastNotOf(TStringView<ElementType> View, size_t Index = INDEX_NONE) const
|
NODISCARD FORCEINLINE size_t FindLastNotOf(TStringView<FElementType> View, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).FindLastNotOf(View, Index);
|
return TStringView<FElementType>(*this).FindLastNotOf(View, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last absence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the last absence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE size_t FindLastNotOf(ElementType Char, size_t Index = INDEX_NONE) const
|
NODISCARD FORCEINLINE size_t FindLastNotOf(FElementType Char, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
checkf(Index == INDEX_NONE || Index < this->Num(), TEXT("Illegal index. Please check Index."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).FindLastNotOf(Char, Index);
|
return TStringView<FElementType>(*this).FindLastNotOf(Char, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -1028,7 +1028,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (this->Max() >= this->Num() + 1)
|
if (this->Max() >= this->Num() + 1)
|
||||||
{
|
{
|
||||||
const_cast<ElementType*>(this->GetData())[this->Num()] = LITERAL(ElementType, '\0');
|
const_cast<FElementType*>(this->GetData())[this->Num()] = LITERAL(FElementType, '\0');
|
||||||
|
|
||||||
return *TStringView(this->GetData(), this->Num() + 1);
|
return *TStringView(this->GetData(), this->Num() + 1);
|
||||||
}
|
}
|
||||||
@ -1052,31 +1052,31 @@ public:
|
|||||||
/** @return true if the string only contains valid characters, false otherwise. */
|
/** @return true if the string only contains valid characters, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool IsValid() const
|
NODISCARD FORCEINLINE bool IsValid() const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).IsValid();
|
return TStringView<FElementType>(*this).IsValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string only contains ASCII characters, false otherwise. */
|
/** @return true if the string only contains ASCII characters, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool IsASCII() const
|
NODISCARD FORCEINLINE bool IsASCII() const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).IsASCII();
|
return TStringView<FElementType>(*this).IsASCII();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string can be fully represented as a boolean value, false otherwise. */
|
/** @return true if the string can be fully represented as a boolean value, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool IsBoolean() const
|
NODISCARD FORCEINLINE bool IsBoolean() const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).IsBoolean();
|
return TStringView<FElementType>(*this).IsBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string can be fully represented as an integer value, false otherwise. */
|
/** @return true if the string can be fully represented as an integer value, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool IsInteger(unsigned Base = 10, bool bSigned = true) const
|
NODISCARD FORCEINLINE bool IsInteger(unsigned Base = 10, bool bSigned = true) const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).IsInteger(Base, bSigned);
|
return TStringView<FElementType>(*this).IsInteger(Base, bSigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string can be fully represented as a floating-point value, false otherwise. */
|
/** @return true if the string can be fully represented as a floating-point value, false otherwise. */
|
||||||
NODISCARD FORCEINLINE bool IsFloatingPoint(bool bFixed = true, bool bScientific = true, bool bSigned = true) const
|
NODISCARD FORCEINLINE bool IsFloatingPoint(bool bFixed = true, bool bScientific = true, bool bSigned = true) const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).IsFloatingPoint(bFixed, bScientific, bSigned);
|
return TStringView<FElementType>(*this).IsFloatingPoint(bFixed, bScientific, bSigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -1202,7 +1202,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
NODISCARD FORCEINLINE bool ToBool() const
|
NODISCARD FORCEINLINE bool ToBool() const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).ToBool();
|
return TStringView<FElementType>(*this).ToBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1223,7 +1223,7 @@ public:
|
|||||||
{
|
{
|
||||||
checkf(Base >= 2 && Base <= 36, TEXT("Illegal base. Please check the base."));
|
checkf(Base >= 2 && Base <= 36, TEXT("Illegal base. Please check the base."));
|
||||||
|
|
||||||
return TStringView<ElementType>(*this).template ToInt<U>(Base);
|
return TStringView<FElementType>(*this).template ToInt<U>(Base);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1244,13 +1244,13 @@ public:
|
|||||||
template <CFloatingPoint U = float> requires (!CConst<U> && !CVolatile<U>)
|
template <CFloatingPoint U = float> requires (!CConst<U> && !CVolatile<U>)
|
||||||
NODISCARD FORCEINLINE U ToFloat(bool bFixed = true, bool bScientific = false) const
|
NODISCARD FORCEINLINE U ToFloat(bool bFixed = true, bool bScientific = false) const
|
||||||
{
|
{
|
||||||
return TStringView<ElementType>(*this).template ToFloat<U>(bFixed, bScientific);
|
return TStringView<FElementType>(*this).template ToFloat<U>(bFixed, bScientific);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converts a string into a boolean value and remove the parsed substring. */
|
/** Converts a string into a boolean value and remove the parsed substring. */
|
||||||
NODISCARD FORCEINLINE bool ToBoolAndTrim()
|
NODISCARD FORCEINLINE bool ToBoolAndTrim()
|
||||||
{
|
{
|
||||||
TStringView<ElementType> View = *this;
|
TStringView<FElementType> View = *this;
|
||||||
|
|
||||||
bool Result = View.ToBoolAndTrim();
|
bool Result = View.ToBoolAndTrim();
|
||||||
|
|
||||||
@ -1265,7 +1265,7 @@ public:
|
|||||||
template <CIntegral U = int> requires (!CSameAs<U, bool> && !CConst<U> && !CVolatile<U>)
|
template <CIntegral U = int> requires (!CSameAs<U, bool> && !CConst<U> && !CVolatile<U>)
|
||||||
NODISCARD FORCEINLINE U ToIntAndTrim(unsigned Base = 10)
|
NODISCARD FORCEINLINE U ToIntAndTrim(unsigned Base = 10)
|
||||||
{
|
{
|
||||||
TStringView<ElementType> View = *this;
|
TStringView<FElementType> View = *this;
|
||||||
|
|
||||||
U Result = View.template ToIntAndTrim<U>(Base);
|
U Result = View.template ToIntAndTrim<U>(Base);
|
||||||
|
|
||||||
@ -1280,7 +1280,7 @@ public:
|
|||||||
template <CFloatingPoint U = float> requires (!CConst<U> && !CVolatile<U>)
|
template <CFloatingPoint U = float> requires (!CConst<U> && !CVolatile<U>)
|
||||||
NODISCARD FORCEINLINE U ToFloatAndTrim(bool bFixed = true, bool bScientific = true)
|
NODISCARD FORCEINLINE U ToFloatAndTrim(bool bFixed = true, bool bScientific = true)
|
||||||
{
|
{
|
||||||
TStringView<ElementType> View = *this;
|
TStringView<FElementType> View = *this;
|
||||||
|
|
||||||
U Result = View.template ToFloatAndTrim<U>(bFixed, bScientific);
|
U Result = View.template ToFloatAndTrim<U>(bFixed, bScientific);
|
||||||
|
|
||||||
@ -1302,7 +1302,7 @@ public:
|
|||||||
* @return The formatted string containing the objects.
|
* @return The formatted string containing the objects.
|
||||||
*/
|
*/
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
NODISCARD static FORCEINLINE TString Format(TStringView<ElementType> Fmt, const Ts&... Args)
|
NODISCARD static FORCEINLINE TString Format(TStringView<FElementType> Fmt, const Ts&... Args)
|
||||||
{
|
{
|
||||||
TString Result;
|
TString Result;
|
||||||
|
|
||||||
@ -1313,7 +1313,7 @@ public:
|
|||||||
|
|
||||||
/** Format some objects using a format string and append to the string. */
|
/** Format some objects using a format string and append to the string. */
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
void AppendFormat(TStringView<ElementType> Fmt, const Ts&... Args);
|
void AppendFormat(TStringView<FElementType> Fmt, const Ts&... Args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a string using a format string to objects.
|
* Parse a string using a format string to objects.
|
||||||
@ -1324,16 +1324,16 @@ public:
|
|||||||
* @return The number of objects successfully parsed.
|
* @return The number of objects successfully parsed.
|
||||||
*/
|
*/
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
FORCEINLINE size_t Parse(TStringView<ElementType> Fmt, Ts&... Args) const
|
FORCEINLINE size_t Parse(TStringView<FElementType> Fmt, Ts&... Args) const
|
||||||
{
|
{
|
||||||
return TStringView(*this).Parse(Fmt, Args...);
|
return TStringView(*this).Parse(Fmt, Args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Parse a string using a format string to objects and remove the parsed substring. */
|
/** Parse a string using a format string to objects and remove the parsed substring. */
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
FORCEINLINE size_t ParseAndTrim(TStringView<ElementType> Fmt, Ts&... Args)
|
FORCEINLINE size_t ParseAndTrim(TStringView<FElementType> Fmt, Ts&... Args)
|
||||||
{
|
{
|
||||||
TStringView<ElementType> View = *this;
|
TStringView<FElementType> View = *this;
|
||||||
|
|
||||||
size_t Result = View.ParseAndTrim(Fmt, Args...);
|
size_t Result = View.ParseAndTrim(Fmt, Args...);
|
||||||
|
|
||||||
@ -1347,10 +1347,10 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/** Overloads the GetTypeHash algorithm for TString. */
|
/** Overloads the GetTypeHash algorithm for TString. */
|
||||||
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TString& A) { return GetTypeHash(TStringView<ElementType>(A)); }
|
NODISCARD friend FORCEINLINE size_t GetTypeHash(const TString& A) { return GetTypeHash(TStringView<FElementType>(A)); }
|
||||||
|
|
||||||
/** Overloads the Swap algorithm for TString. */
|
/** Overloads the Swap algorithm for TString. */
|
||||||
friend FORCEINLINE void Swap(TString& A, TString& B) { Swap(static_cast<Super&>(A), static_cast<Super&>(B)); }
|
friend FORCEINLINE void Swap(TString& A, TString& B) { Swap(static_cast<FSuper&>(A), static_cast<FSuper&>(B)); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1373,7 +1373,7 @@ using FU16String = TString<u16char>;
|
|||||||
using FU32String = TString<u32char>;
|
using FU32String = TString<u32char>;
|
||||||
using FUnicodeString = TString<unicodechar>;
|
using FUnicodeString = TString<unicodechar>;
|
||||||
|
|
||||||
template <CCharType T> template <typename Allocator> constexpr TStringView<T>::TStringView(const TString<ElementType, Allocator>& InString)
|
template <CCharType T> template <typename Allocator> constexpr TStringView<T>::TStringView(const TString<FElementType, Allocator>& InString)
|
||||||
: TStringView(InString.GetData(), InString.Num()) { }
|
: TStringView(InString.GetData(), InString.Num()) { }
|
||||||
|
|
||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
|
@ -82,36 +82,36 @@ class TStringView : public TArrayView<const T>
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Super = TArrayView<const T>;
|
using FSuper = TArrayView<const T>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = T;
|
using FElementType = T;
|
||||||
|
|
||||||
using Reference = typename Super::Reference;
|
using FReference = typename FSuper::FReference;
|
||||||
|
|
||||||
using Iterator = typename Super::Iterator;
|
using FIterator = typename FSuper:: FIterator;
|
||||||
using ReverseIterator = typename Super::ReverseIterator;
|
using FReverseIterator = typename FSuper::FReverseIterator;
|
||||||
|
|
||||||
static_assert(CContiguousIterator<Iterator>);
|
static_assert(CContiguousIterator<FIterator>);
|
||||||
|
|
||||||
/** Constructs an empty string view. */
|
/** Constructs an empty string view. */
|
||||||
FORCEINLINE constexpr TStringView() = default;
|
FORCEINLINE constexpr TStringView() = default;
|
||||||
|
|
||||||
/** Constructs a string view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */
|
/** Constructs a string view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */
|
||||||
template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const ElementType(*)[]>)
|
template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const FElementType(*)[]>)
|
||||||
FORCEINLINE constexpr TStringView(I InFirst, size_t InCount) : Super(InFirst, InCount) { }
|
FORCEINLINE constexpr TStringView(I InFirst, size_t InCount) : FSuper(InFirst, InCount) { }
|
||||||
|
|
||||||
/** Constructs a string view that is a view over the range ['InFirst', 'InLast'). */
|
/** Constructs a string view that is a view over the range ['InFirst', 'InLast'). */
|
||||||
template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const ElementType(*)[]>)
|
template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const FElementType(*)[]>)
|
||||||
FORCEINLINE constexpr TStringView(I InFirst, S InLast) : Super(InFirst, InLast) { }
|
FORCEINLINE constexpr TStringView(I InFirst, S InLast) : FSuper(InFirst, InLast) { }
|
||||||
|
|
||||||
/** Constructs a string view that is a view over the string 'InString'. */
|
/** Constructs a string view that is a view over the string 'InString'. */
|
||||||
template <typename Allocator>
|
template <typename Allocator>
|
||||||
FORCEINLINE constexpr TStringView(const TString<ElementType, Allocator>& InString);
|
FORCEINLINE constexpr TStringView(const TString<FElementType, Allocator>& InString);
|
||||||
|
|
||||||
/** Constructs a string view that is a view over the range ['InPtr', 'InPtr' + 'Count'). */
|
/** Constructs a string view that is a view over the range ['InPtr', 'InPtr' + 'Count'). */
|
||||||
FORCEINLINE constexpr TStringView(const ElementType* InPtr, size_t Count) : Super(InPtr, Count)
|
FORCEINLINE constexpr TStringView(const FElementType* InPtr, size_t Count) : FSuper(InPtr, Count)
|
||||||
{
|
{
|
||||||
checkf(InPtr != nullptr, TEXT("TStringView cannot be initialized by nullptr. Please check the pointer."));
|
checkf(InPtr != nullptr, TEXT("TStringView cannot be initialized by nullptr. Please check the pointer."));
|
||||||
}
|
}
|
||||||
@ -119,23 +119,23 @@ public:
|
|||||||
FORCEINLINE constexpr TStringView(nullptr_t, size_t) = delete;
|
FORCEINLINE constexpr TStringView(nullptr_t, size_t) = delete;
|
||||||
|
|
||||||
/** Constructs a string view that is a view over the range ['InPtr', '\0'). */
|
/** Constructs a string view that is a view over the range ['InPtr', '\0'). */
|
||||||
FORCEINLINE constexpr TStringView(const ElementType* InPtr)
|
FORCEINLINE constexpr TStringView(const FElementType* InPtr)
|
||||||
{
|
{
|
||||||
checkf(InPtr != nullptr, TEXT("TStringView cannot be initialized by nullptr. Please check the pointer."));
|
checkf(InPtr != nullptr, TEXT("TStringView cannot be initialized by nullptr. Please check the pointer."));
|
||||||
|
|
||||||
size_t Length = 0;
|
size_t Length = 0;
|
||||||
|
|
||||||
if constexpr (CSameAs<ElementType, char>)
|
if constexpr (CSameAs<FElementType, char>)
|
||||||
{
|
{
|
||||||
Length = NAMESPACE_STD::strlen(InPtr);
|
Length = NAMESPACE_STD::strlen(InPtr);
|
||||||
}
|
}
|
||||||
else if constexpr (CSameAs<ElementType, wchar>)
|
else if constexpr (CSameAs<FElementType, wchar>)
|
||||||
{
|
{
|
||||||
Length = NAMESPACE_STD::wcslen(InPtr);
|
Length = NAMESPACE_STD::wcslen(InPtr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (InPtr[Length] != LITERAL(ElementType, '\0')) ++Length;
|
while (InPtr[Length] != LITERAL(FElementType, '\0')) ++Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
*this = TStringView(InPtr, Length);
|
*this = TStringView(InPtr, Length);
|
||||||
@ -150,18 +150,18 @@ public:
|
|||||||
FORCEINLINE constexpr TStringView& operator=(const TStringView&) noexcept = default;
|
FORCEINLINE constexpr TStringView& operator=(const TStringView&) noexcept = default;
|
||||||
|
|
||||||
/** Compares the contents of two string views. */
|
/** Compares the contents of two string views. */
|
||||||
NODISCARD friend constexpr bool operator==(TStringView LHS, TStringView RHS) { return static_cast<Super>(LHS) == static_cast<Super>(RHS); }
|
NODISCARD friend constexpr bool operator==(TStringView LHS, TStringView RHS) { return static_cast<FSuper>(LHS) == static_cast<FSuper>(RHS); }
|
||||||
|
|
||||||
/** Compares the contents of a string view and a character. */
|
/** Compares the contents of a string view and a character. */
|
||||||
NODISCARD friend constexpr bool operator==(TStringView LHS, ElementType RHS) { return LHS == TStringView(&RHS, 1); }
|
NODISCARD friend constexpr bool operator==(TStringView LHS, FElementType RHS) { return LHS == TStringView(&RHS, 1); }
|
||||||
NODISCARD friend constexpr bool operator==(ElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) == RHS; }
|
NODISCARD friend constexpr bool operator==(FElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) == RHS; }
|
||||||
|
|
||||||
/** Compares the contents of two string views. */
|
/** Compares the contents of two string views. */
|
||||||
NODISCARD friend constexpr auto operator<=>(TStringView LHS, TStringView RHS) { return static_cast<Super>(LHS) <=> static_cast<Super>(RHS); }
|
NODISCARD friend constexpr auto operator<=>(TStringView LHS, TStringView RHS) { return static_cast<FSuper>(LHS) <=> static_cast<FSuper>(RHS); }
|
||||||
|
|
||||||
/** Compares the contents of a string view and a character. */
|
/** Compares the contents of a string view and a character. */
|
||||||
NODISCARD friend constexpr auto operator<=>(TStringView LHS, ElementType RHS) { return LHS <=> TStringView(&RHS, 1); }
|
NODISCARD friend constexpr auto operator<=>(TStringView LHS, FElementType RHS) { return LHS <=> TStringView(&RHS, 1); }
|
||||||
NODISCARD friend constexpr auto operator<=>(ElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) <=> RHS; }
|
NODISCARD friend constexpr auto operator<=>(FElementType LHS, TStringView RHS) { return TStringView(&LHS, 1) <=> RHS; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ public:
|
|||||||
/** Removes whitespace characters from the start of this string. */
|
/** Removes whitespace characters from the start of this string. */
|
||||||
FORCEINLINE constexpr TStringView& TrimStart()
|
FORCEINLINE constexpr TStringView& TrimStart()
|
||||||
{
|
{
|
||||||
auto Index = Find([](ElementType Char) { return !TChar<ElementType>::IsSpace(Char); });
|
auto Index = Find([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); });
|
||||||
|
|
||||||
if (Index != INDEX_NONE)
|
if (Index != INDEX_NONE)
|
||||||
{
|
{
|
||||||
@ -202,7 +202,7 @@ public:
|
|||||||
/** Removes whitespace characters from the end of this string. */
|
/** Removes whitespace characters from the end of this string. */
|
||||||
FORCEINLINE constexpr TStringView& TrimEnd()
|
FORCEINLINE constexpr TStringView& TrimEnd()
|
||||||
{
|
{
|
||||||
auto Index = RFind([](ElementType Char) { return !TChar<ElementType>::IsSpace(Char); });
|
auto Index = RFind([](FElementType Char) { return !TChar<FElementType>::IsSpace(Char); });
|
||||||
|
|
||||||
if (Index != INDEX_NONE)
|
if (Index != INDEX_NONE)
|
||||||
{
|
{
|
||||||
@ -225,7 +225,7 @@ public:
|
|||||||
/** Removes characters after the first null-terminator. */
|
/** Removes characters after the first null-terminator. */
|
||||||
FORCEINLINE constexpr TStringView& TrimToNullTerminator()
|
FORCEINLINE constexpr TStringView& TrimToNullTerminator()
|
||||||
{
|
{
|
||||||
auto Index = Find(LITERAL(ElementType, '\0'));
|
auto Index = Find(LITERAL(FElementType, '\0'));
|
||||||
|
|
||||||
if (Index != INDEX_NONE)
|
if (Index != INDEX_NONE)
|
||||||
{
|
{
|
||||||
@ -238,7 +238,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/** Copies the elements of this string view to the destination buffer without null-termination. */
|
/** Copies the elements of this string view to the destination buffer without null-termination. */
|
||||||
FORCEINLINE constexpr size_t Copy(ElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const
|
FORCEINLINE constexpr size_t Copy(FElementType* Dest, size_t Count = DynamicExtent, size_t Offset = 0) const
|
||||||
{
|
{
|
||||||
checkf(Dest != nullptr, TEXT("Illegal destination buffer. Please check the pointer."));
|
checkf(Dest != nullptr, TEXT("Illegal destination buffer. Please check the pointer."));
|
||||||
|
|
||||||
@ -277,7 +277,7 @@ public:
|
|||||||
{
|
{
|
||||||
checkf(Offset <= this->Num() && (Count == DynamicExtent || Offset + Count <= this->Num()), TEXT("Illegal subview range. Please check Offset and Count."));
|
checkf(Offset <= this->Num() && (Count == DynamicExtent || Offset + Count <= this->Num()), TEXT("Illegal subview range. Please check Offset and Count."));
|
||||||
|
|
||||||
Super Temp = this->Subview(Offset, Count);
|
FSuper Temp = this->Subview(Offset, Count);
|
||||||
|
|
||||||
return TStringView(Temp.GetData(), Temp.Num());
|
return TStringView(Temp.GetData(), Temp.Num());
|
||||||
}
|
}
|
||||||
@ -289,7 +289,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string view starts with the given prefix, false otherwise. */
|
/** @return true if the string view starts with the given prefix, false otherwise. */
|
||||||
NODISCARD FORCEINLINE constexpr bool StartsWith(ElementType Prefix) const
|
NODISCARD FORCEINLINE constexpr bool StartsWith(FElementType Prefix) const
|
||||||
{
|
{
|
||||||
return this->Num() >= 1 && this->Front() == Prefix;
|
return this->Num() >= 1 && this->Front() == Prefix;
|
||||||
}
|
}
|
||||||
@ -301,7 +301,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string view ends with the given suffix, false otherwise. */
|
/** @return true if the string view ends with the given suffix, false otherwise. */
|
||||||
NODISCARD FORCEINLINE constexpr bool EndsWith(ElementType Suffix) const
|
NODISCARD FORCEINLINE constexpr bool EndsWith(FElementType Suffix) const
|
||||||
{
|
{
|
||||||
return this->Num() >= 1 && this->Back() == Suffix;
|
return this->Num() >= 1 && this->Back() == Suffix;
|
||||||
}
|
}
|
||||||
@ -313,13 +313,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string view contains the given character, false otherwise. */
|
/** @return true if the string view contains the given character, false otherwise. */
|
||||||
NODISCARD FORCEINLINE constexpr bool Contains(ElementType Char) const
|
NODISCARD FORCEINLINE constexpr bool Contains(FElementType Char) const
|
||||||
{
|
{
|
||||||
return Find(Char) != INDEX_NONE;
|
return Find(Char) != INDEX_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the string view contains character that satisfy the given predicate, false otherwise. */
|
/** @return true if the string view contains character that satisfy the given predicate, false otherwise. */
|
||||||
template <CPredicate<ElementType> F>
|
template <CPredicate<FElementType> F>
|
||||||
NODISCARD FORCEINLINE constexpr bool Contains(F&& InPredicate) const
|
NODISCARD FORCEINLINE constexpr bool Contains(F&& InPredicate) const
|
||||||
{
|
{
|
||||||
return Find(Forward<F>(InPredicate)) != INDEX_NONE;
|
return Find(Forward<F>(InPredicate)) != INDEX_NONE;
|
||||||
@ -346,7 +346,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD constexpr size_t Find(ElementType Char, size_t Index = 0) const
|
NODISCARD constexpr size_t Find(FElementType Char, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
if (Index >= this->Num()) return INDEX_NONE;
|
if (Index >= this->Num()) return INDEX_NONE;
|
||||||
|
|
||||||
@ -362,7 +362,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the first occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
|
/** @return The index of the first occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
|
||||||
template <CPredicate<ElementType> F>
|
template <CPredicate<FElementType> F>
|
||||||
NODISCARD constexpr size_t Find(F&& InPredicate, size_t Index = 0) const
|
NODISCARD constexpr size_t Find(F&& InPredicate, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
if (Index >= this->Num()) return INDEX_NONE;
|
if (Index >= this->Num()) return INDEX_NONE;
|
||||||
@ -401,7 +401,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD constexpr size_t RFind(ElementType Char, size_t Index = INDEX_NONE) const
|
NODISCARD constexpr size_t RFind(FElementType Char, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
if (Index != INDEX_NONE && Index >= this->Num()) return INDEX_NONE;
|
if (Index != INDEX_NONE && Index >= this->Num()) return INDEX_NONE;
|
||||||
|
|
||||||
@ -419,7 +419,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
|
/** @return The index of the last occurrence of the character that satisfy the given predicate, or INDEX_NONE if not found. */
|
||||||
template <CPredicate<ElementType> F>
|
template <CPredicate<FElementType> F>
|
||||||
NODISCARD constexpr size_t RFind(F&& InPredicate, size_t Index = INDEX_NONE) const
|
NODISCARD constexpr size_t RFind(F&& InPredicate, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
if (Index != INDEX_NONE && Index >= this->Num()) return INDEX_NONE;
|
if (Index != INDEX_NONE && Index >= this->Num()) return INDEX_NONE;
|
||||||
@ -440,11 +440,11 @@ public:
|
|||||||
/** @return The index of the first occurrence of the character contained in the given view, or INDEX_NONE if not found. */
|
/** @return The index of the first occurrence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t FindFirstOf(TStringView View, size_t Index = 0) const
|
NODISCARD FORCEINLINE constexpr size_t FindFirstOf(TStringView View, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
return Find([View](ElementType Char) { return View.Contains(Char); }, Index);
|
return Find([View](FElementType Char) { return View.Contains(Char); }, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the first occurrence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t FindFirstOf(ElementType Char, size_t Index = 0) const
|
NODISCARD FORCEINLINE constexpr size_t FindFirstOf(FElementType Char, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
return Find(Char, Index);
|
return Find(Char, Index);
|
||||||
}
|
}
|
||||||
@ -452,11 +452,11 @@ public:
|
|||||||
/** @return The index of the last occurrence of the character contained in the given view, or INDEX_NONE if not found. */
|
/** @return The index of the last occurrence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t FindLastOf(TStringView View, size_t Index = INDEX_NONE) const
|
NODISCARD FORCEINLINE constexpr size_t FindLastOf(TStringView View, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
return RFind([View](ElementType Char) { return View.Contains(Char); }, Index);
|
return RFind([View](FElementType Char) { return View.Contains(Char); }, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the last occurrence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t FindLastOf(ElementType Char, size_t Index = INDEX_NONE) const
|
NODISCARD FORCEINLINE constexpr size_t FindLastOf(FElementType Char, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
return RFind(Char, Index);
|
return RFind(Char, Index);
|
||||||
}
|
}
|
||||||
@ -464,25 +464,25 @@ public:
|
|||||||
/** @return The index of the first absence of the character contained in the given view, or INDEX_NONE if not found. */
|
/** @return The index of the first absence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t FindFirstNotOf(TStringView View, size_t Index = 0) const
|
NODISCARD FORCEINLINE constexpr size_t FindFirstNotOf(TStringView View, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
return Find([View](ElementType Char) { return !View.Contains(Char); }, Index);
|
return Find([View](FElementType Char) { return !View.Contains(Char); }, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the first absence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the first absence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t FindFirstNotOf(ElementType Char, size_t Index = 0) const
|
NODISCARD FORCEINLINE constexpr size_t FindFirstNotOf(FElementType Char, size_t Index = 0) const
|
||||||
{
|
{
|
||||||
return Find([Char](ElementType C) { return C != Char; }, Index);
|
return Find([Char](FElementType C) { return C != Char; }, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last absence of the character contained in the given view, or INDEX_NONE if not found. */
|
/** @return The index of the last absence of the character contained in the given view, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t FindLastNotOf(TStringView View, size_t Index = INDEX_NONE) const
|
NODISCARD FORCEINLINE constexpr size_t FindLastNotOf(TStringView View, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
return RFind([View](ElementType Char) { return !View.Contains(Char); }, Index);
|
return RFind([View](FElementType Char) { return !View.Contains(Char); }, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return The index of the last absence of the given character, or INDEX_NONE if not found. */
|
/** @return The index of the last absence of the given character, or INDEX_NONE if not found. */
|
||||||
NODISCARD FORCEINLINE constexpr size_t FindLastNotOf(ElementType Char, size_t Index = INDEX_NONE) const
|
NODISCARD FORCEINLINE constexpr size_t FindLastNotOf(FElementType Char, size_t Index = INDEX_NONE) const
|
||||||
{
|
{
|
||||||
return RFind([Char](ElementType C) { return C != Char; }, Index);
|
return RFind([Char](FElementType C) { return C != Char; }, Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -490,18 +490,18 @@ public:
|
|||||||
/** @return The non-modifiable standard C character string version of the string view. */
|
/** @return The non-modifiable standard C character string version of the string view. */
|
||||||
NODISCARD FORCEINLINE auto operator*() const
|
NODISCARD FORCEINLINE auto operator*() const
|
||||||
{
|
{
|
||||||
if (this->Back() == LITERAL(ElementType, '\0') || Contains(LITERAL(ElementType, '\0')))
|
if (this->Back() == LITERAL(FElementType, '\0') || Contains(LITERAL(FElementType, '\0')))
|
||||||
{
|
{
|
||||||
return NAMESPACE_PRIVATE::TCStringFromTStringView<ElementType>(this->GetData(), false);
|
return NAMESPACE_PRIVATE::TCStringFromTStringView<FElementType>(this->GetData(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementType* Buffer = new ElementType[this->Num() + 1];
|
FElementType* Buffer = new FElementType[this->Num() + 1];
|
||||||
|
|
||||||
Copy(Buffer);
|
Copy(Buffer);
|
||||||
|
|
||||||
Buffer[this->Num()] = LITERAL(ElementType, '\0');
|
Buffer[this->Num()] = LITERAL(FElementType, '\0');
|
||||||
|
|
||||||
return NAMESPACE_PRIVATE::TCStringFromTStringView<ElementType>(Buffer, true);
|
return NAMESPACE_PRIVATE::TCStringFromTStringView<FElementType>(Buffer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -509,9 +509,9 @@ public:
|
|||||||
/** @return true if the string only contains valid characters, false otherwise. */
|
/** @return true if the string only contains valid characters, false otherwise. */
|
||||||
NODISCARD constexpr bool IsValid() const
|
NODISCARD constexpr bool IsValid() const
|
||||||
{
|
{
|
||||||
for (ElementType Char : *this)
|
for (FElementType Char : *this)
|
||||||
{
|
{
|
||||||
if (!TChar<ElementType>::IsValid(Char)) return false;
|
if (!TChar<FElementType>::IsValid(Char)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -520,9 +520,9 @@ public:
|
|||||||
/** @return true if the string only contains ASCII characters, false otherwise. */
|
/** @return true if the string only contains ASCII characters, false otherwise. */
|
||||||
NODISCARD constexpr bool IsASCII() const
|
NODISCARD constexpr bool IsASCII() const
|
||||||
{
|
{
|
||||||
for (ElementType Char : *this)
|
for (FElementType Char : *this)
|
||||||
{
|
{
|
||||||
if (!TChar<ElementType>::IsASCII(Char)) return false;
|
if (!TChar<FElementType>::IsASCII(Char)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -543,7 +543,7 @@ public:
|
|||||||
{
|
{
|
||||||
TStringView View = *this;
|
TStringView View = *this;
|
||||||
|
|
||||||
if (View.StartsWith(LITERAL(ElementType, '-')))
|
if (View.StartsWith(LITERAL(FElementType, '-')))
|
||||||
{
|
{
|
||||||
if (bSigned) View.RemovePrefix(1);
|
if (bSigned) View.RemovePrefix(1);
|
||||||
else return false;
|
else return false;
|
||||||
@ -559,7 +559,7 @@ public:
|
|||||||
{
|
{
|
||||||
TStringView View = *this;
|
TStringView View = *this;
|
||||||
|
|
||||||
if (View.StartsWith(LITERAL(ElementType, '-')))
|
if (View.StartsWith(LITERAL(FElementType, '-')))
|
||||||
{
|
{
|
||||||
if (bSigned) View.RemovePrefix(1);
|
if (bSigned) View.RemovePrefix(1);
|
||||||
else return false;
|
else return false;
|
||||||
@ -659,7 +659,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/** Overloads the GetTypeHash algorithm for TStringView. */
|
/** Overloads the GetTypeHash algorithm for TStringView. */
|
||||||
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(TStringView A) { return GetTypeHash(static_cast<Super>(A)); }
|
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(TStringView A) { return GetTypeHash(static_cast<FSuper>(A)); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -676,6 +676,8 @@ using FU16StringView = TStringView<u16char>;
|
|||||||
using FU32StringView = TStringView<u32char>;
|
using FU32StringView = TStringView<u32char>;
|
||||||
using FUnicodeStringView = TStringView<unicodechar>;
|
using FUnicodeStringView = TStringView<unicodechar>;
|
||||||
|
|
||||||
|
// ReSharper disable CppInconsistentNaming
|
||||||
|
|
||||||
#define TEXT_VIEW(X) TStringView(TEXT(X))
|
#define TEXT_VIEW(X) TStringView(TEXT(X))
|
||||||
#define WTEXT_VIEW(X) TStringView(WTEXT(X))
|
#define WTEXT_VIEW(X) TStringView(WTEXT(X))
|
||||||
#define U8TEXT_VIEW(X) TStringView(U8TEXT(X))
|
#define U8TEXT_VIEW(X) TStringView(U8TEXT(X))
|
||||||
@ -685,6 +687,8 @@ using FUnicodeStringView = TStringView<unicodechar>;
|
|||||||
|
|
||||||
#define LITERAL_VIEW(T, X) TStringView(LITERAL(T, X))
|
#define LITERAL_VIEW(T, X) TStringView(LITERAL(T, X))
|
||||||
|
|
||||||
|
// ReSharper restore CppInconsistentNaming
|
||||||
|
|
||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
NAMESPACE_MODULE_END(Redcraft)
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
NAMESPACE_REDCRAFT_END
|
NAMESPACE_REDCRAFT_END
|
||||||
|
@ -244,19 +244,19 @@ public:
|
|||||||
&& NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, T&&>)
|
&& NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, T&&>)
|
||||||
FORCEINLINE FAny& operator=(T&& InValue)
|
FORCEINLINE FAny& operator=(T&& InValue)
|
||||||
{
|
{
|
||||||
using DecayedType = TDecay<T>;
|
using FDecayedType = TDecay<T>;
|
||||||
|
|
||||||
if constexpr (CAssignableFrom<DecayedType, T&&>)
|
if constexpr (CAssignableFrom<FDecayedType, T&&>)
|
||||||
{
|
{
|
||||||
if (HoldsAlternative<DecayedType>())
|
if (HoldsAlternative<FDecayedType>())
|
||||||
{
|
{
|
||||||
GetValue<DecayedType>() = Forward<T>(InValue);
|
GetValue<FDecayedType>() = Forward<T>(InValue);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Destroy();
|
Destroy();
|
||||||
EmplaceImpl<DecayedType>(Forward<T>(InValue));
|
EmplaceImpl<FDecayedType>(Forward<T>(InValue));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -540,32 +540,32 @@ private:
|
|||||||
template <typename T, typename... Ts>
|
template <typename T, typename... Ts>
|
||||||
void EmplaceImpl(Ts&&... Args)
|
void EmplaceImpl(Ts&&... Args)
|
||||||
{
|
{
|
||||||
using DecayedType = TDecay<T>;
|
using FDecayedType = TDecay<T>;
|
||||||
|
|
||||||
TypeInfo = reinterpret_cast<uintptr>(&typeid(DecayedType));
|
TypeInfo = reinterpret_cast<uintptr>(&typeid(FDecayedType));
|
||||||
|
|
||||||
if constexpr (CEmpty<DecayedType> && CTrivial<DecayedType>) return; // ERepresentation::Empty
|
if constexpr (CEmpty<FDecayedType> && CTrivial<FDecayedType>) return; // ERepresentation::Empty
|
||||||
|
|
||||||
constexpr bool bIsTriviallyStorable = sizeof(DecayedType) <= sizeof(TrivialStorage.Internal) && alignof(DecayedType) <= alignof(FAny) && CTriviallyCopyable<DecayedType>;
|
constexpr bool bIsTriviallyStorable = sizeof(FDecayedType) <= sizeof(TrivialStorage.Internal) && alignof(FDecayedType) <= alignof(FAny) && CTriviallyCopyable<FDecayedType>;
|
||||||
constexpr bool bIsSmallStorable = sizeof(DecayedType) <= sizeof( SmallStorage.Internal) && alignof(DecayedType) <= alignof(FAny);
|
constexpr bool bIsSmallStorable = sizeof(FDecayedType) <= sizeof( SmallStorage.Internal) && alignof(FDecayedType) <= alignof(FAny);
|
||||||
|
|
||||||
static constexpr const FRTTI SelectedRTTI(InPlaceType<DecayedType>);
|
static constexpr const FRTTI SelectedRTTI(InPlaceType<FDecayedType>);
|
||||||
|
|
||||||
if constexpr (bIsTriviallyStorable)
|
if constexpr (bIsTriviallyStorable)
|
||||||
{
|
{
|
||||||
new (&TrivialStorage.Internal) DecayedType(Forward<Ts>(Args)...);
|
new (&TrivialStorage.Internal) FDecayedType(Forward<Ts>(Args)...);
|
||||||
TypeInfo |= static_cast<uintptr>(ERepresentation::Trivial);
|
TypeInfo |= static_cast<uintptr>(ERepresentation::Trivial);
|
||||||
}
|
}
|
||||||
else if constexpr (bIsSmallStorable)
|
else if constexpr (bIsSmallStorable)
|
||||||
{
|
{
|
||||||
new (&SmallStorage.Internal) DecayedType(Forward<Ts>(Args)...);
|
new (&SmallStorage.Internal) FDecayedType(Forward<Ts>(Args)...);
|
||||||
SmallStorage.RTTI = &SelectedRTTI;
|
SmallStorage.RTTI = &SelectedRTTI;
|
||||||
TypeInfo |= static_cast<uintptr>(ERepresentation::Small);
|
TypeInfo |= static_cast<uintptr>(ERepresentation::Small);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BigStorage.External = Memory::Malloc(sizeof(DecayedType), alignof(DecayedType));
|
BigStorage.External = Memory::Malloc(sizeof(FDecayedType), alignof(FDecayedType));
|
||||||
new (BigStorage.External) DecayedType(Forward<Ts>(Args)...);
|
new (BigStorage.External) FDecayedType(Forward<Ts>(Args)...);
|
||||||
BigStorage.RTTI = &SelectedRTTI;
|
BigStorage.RTTI = &SelectedRTTI;
|
||||||
TypeInfo |= static_cast<uintptr>(ERepresentation::Big);
|
TypeInfo |= static_cast<uintptr>(ERepresentation::Big);
|
||||||
}
|
}
|
||||||
|
@ -68,48 +68,48 @@ struct TAtomicImpl : FSingleton
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
using NativeAtomicType = TConditional<bIsRef, NAMESPACE_STD::atomic_ref<T>, NAMESPACE_STD::atomic<T>>;
|
using FNativeAtomic = TConditional<bIsRef, NAMESPACE_STD::atomic_ref<T>, NAMESPACE_STD::atomic<T>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ValueType = T;
|
using FValueType = T;
|
||||||
|
|
||||||
/** Indicates that the type is always lock-free */
|
/** Indicates that the type is always lock-free */
|
||||||
static constexpr bool bIsAlwaysLockFree = NativeAtomicType::is_always_lock_free;
|
static constexpr bool bIsAlwaysLockFree = FNativeAtomic::is_always_lock_free;
|
||||||
|
|
||||||
/** Indicates the required alignment of an object to be referenced by TAtomicRef. */
|
/** Indicates the required alignment of an object to be referenced by TAtomicRef. */
|
||||||
static constexpr size_t RequiredAlignment = NAMESPACE_STD::atomic_ref<T>::required_alignment;
|
static constexpr size_t RequiredAlignment = NAMESPACE_STD::atomic_ref<T>::required_alignment;
|
||||||
|
|
||||||
/** Constructs an atomic object. */
|
/** Constructs an atomic object. */
|
||||||
FORCEINLINE constexpr TAtomicImpl() requires (!bIsRef) : NativeAtomic() { };
|
FORCEINLINE constexpr TAtomicImpl() requires (!bIsRef) : NativeAtomic() { }
|
||||||
FORCEINLINE constexpr TAtomicImpl(ValueType Desired) requires (!bIsRef) : NativeAtomic(Desired) { };
|
FORCEINLINE constexpr TAtomicImpl(FValueType Desired) requires (!bIsRef) : NativeAtomic(Desired) { }
|
||||||
|
|
||||||
/** Constructs an atomic reference. */
|
/** Constructs an atomic reference. */
|
||||||
FORCEINLINE explicit TAtomicImpl(ValueType& Desired) requires (bIsRef) : NativeAtomic(Desired) { check(Memory::IsAligned(&Desired, RequiredAlignment)); };
|
FORCEINLINE explicit TAtomicImpl(FValueType& Desired) requires (bIsRef) : NativeAtomic(Desired) { check(Memory::IsAligned(&Desired, RequiredAlignment)); }
|
||||||
FORCEINLINE TAtomicImpl(TAtomicImpl& InValue) requires (bIsRef) : NativeAtomic(InValue) { };
|
FORCEINLINE TAtomicImpl(TAtomicImpl& InValue) requires (bIsRef) : NativeAtomic(InValue) { }
|
||||||
|
|
||||||
/** Stores a value into an atomic object. */
|
/** Stores a value into an atomic object. */
|
||||||
FORCEINLINE ValueType operator=(ValueType Desired) { return NativeAtomic = Desired; }
|
FORCEINLINE FValueType operator=(FValueType Desired) { return NativeAtomic = Desired; }
|
||||||
FORCEINLINE ValueType operator=(ValueType Desired) volatile requires (bIsAlwaysLockFree) { return NativeAtomic = Desired; }
|
FORCEINLINE FValueType operator=(FValueType Desired) volatile requires (bIsAlwaysLockFree) { return NativeAtomic = Desired; }
|
||||||
|
|
||||||
/** Atomically replaces the value of the atomic object with a non-atomic argument. */
|
/** Atomically replaces the value of the atomic object with a non-atomic argument. */
|
||||||
FORCEINLINE void Store(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.store(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE void Store(FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.store(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
FORCEINLINE void Store(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.store(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE void Store(FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.store(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
|
||||||
/** Atomically obtains the value of the atomic object. */
|
/** Atomically obtains the value of the atomic object. */
|
||||||
NODISCARD FORCEINLINE ValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.load(static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
NODISCARD FORCEINLINE FValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.load(static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
NODISCARD FORCEINLINE ValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.load(static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
NODISCARD FORCEINLINE FValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.load(static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
|
||||||
/** Loads a value from an atomic object. */
|
/** Loads a value from an atomic object. */
|
||||||
NODISCARD FORCEINLINE operator ValueType() const { return static_cast<ValueType>(NativeAtomic); }
|
NODISCARD FORCEINLINE operator FValueType() const { return static_cast<FValueType>(NativeAtomic); }
|
||||||
NODISCARD FORCEINLINE operator ValueType() const volatile requires (bIsAlwaysLockFree) { return static_cast<ValueType>(NativeAtomic); }
|
NODISCARD FORCEINLINE operator FValueType() const volatile requires (bIsAlwaysLockFree) { return static_cast<FValueType>(NativeAtomic); }
|
||||||
|
|
||||||
/** Atomically replaces the value of the atomic object and obtains the value held previously. */
|
/** Atomically replaces the value of the atomic object and obtains the value held previously. */
|
||||||
NODISCARD FORCEINLINE ValueType Exchange(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { return NativeAtomic.exchange(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
NODISCARD FORCEINLINE FValueType Exchange(FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { return NativeAtomic.exchange(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
NODISCARD FORCEINLINE ValueType Exchange(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { return NativeAtomic.exchange(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
NODISCARD FORCEINLINE FValueType Exchange(FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { return NativeAtomic.exchange(Desired, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
|
||||||
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
|
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
|
||||||
NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false)
|
NODISCARD FORCEINLINE bool CompareExchange(FValueType& Expected, FValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false)
|
||||||
{
|
{
|
||||||
MEMORY_ORDER_CHECK(Failure, 0x01 | 0x02 | 0x04 | 0x20);
|
MEMORY_ORDER_CHECK(Failure, 0x01 | 0x02 | 0x04 | 0x20);
|
||||||
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Success), static_cast<NAMESPACE_STD::memory_order>(Failure));
|
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Success), static_cast<NAMESPACE_STD::memory_order>(Failure));
|
||||||
@ -117,7 +117,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
|
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
|
||||||
NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree)
|
NODISCARD FORCEINLINE bool CompareExchange(FValueType& Expected, FValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree)
|
||||||
{
|
{
|
||||||
MEMORY_ORDER_CHECK(Failure, 0x01 | 0x02 | 0x04 | 0x20);
|
MEMORY_ORDER_CHECK(Failure, 0x01 | 0x02 | 0x04 | 0x20);
|
||||||
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Success), static_cast<NAMESPACE_STD::memory_order>(Failure));
|
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Success), static_cast<NAMESPACE_STD::memory_order>(Failure));
|
||||||
@ -125,162 +125,162 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
|
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
|
||||||
NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false)
|
NODISCARD FORCEINLINE bool CompareExchange(FValueType& Expected, FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false)
|
||||||
{
|
{
|
||||||
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
|
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
|
||||||
else return NativeAtomic.compare_exchange_strong(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
|
else return NativeAtomic.compare_exchange_strong(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
|
/** Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not. */
|
||||||
NODISCARD FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree)
|
NODISCARD FORCEINLINE bool CompareExchange(FValueType& Expected, FValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree)
|
||||||
{
|
{
|
||||||
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
|
if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
|
||||||
else return NativeAtomic.compare_exchange_strong(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
|
else return NativeAtomic.compare_exchange_strong(Expected, Desired, static_cast<NAMESPACE_STD::memory_order>(Order));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Blocks the thread until notified and the atomic value changes. */
|
/** Blocks the thread until notified and the atomic value changes. */
|
||||||
FORCEINLINE void Wait(ValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); NativeAtomic.wait(Old, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE void Wait(FValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); NativeAtomic.wait(Old, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
FORCEINLINE void Wait(ValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); NativeAtomic.wait(Old, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE void Wait(FValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); NativeAtomic.wait(Old, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
|
||||||
/** Notifies at least one or all threads blocked waiting on the atomic object. */
|
/** Notifies at least one or all threads blocked waiting on the atomic object. */
|
||||||
FORCEINLINE void Notify(bool bIsAll = false) { if (bIsAll) NativeAtomic.notify_all(); else NativeAtomic.notify_one(); }
|
FORCEINLINE void Notify(bool bIsAll = false) { if (bIsAll) NativeAtomic.notify_all(); else NativeAtomic.notify_one(); }
|
||||||
FORCEINLINE void Notify(bool bIsAll = false) volatile { if (bIsAll) NativeAtomic.notify_all(); else NativeAtomic.notify_one(); }
|
FORCEINLINE void Notify(bool bIsAll = false) volatile { if (bIsAll) NativeAtomic.notify_all(); else NativeAtomic.notify_one(); }
|
||||||
|
|
||||||
/** Atomically executes the 'Func' on the value stored in the atomic object and obtains the value held previously. */
|
/** Atomically executes the 'Func' on the value stored in the atomic object and obtains the value held previously. */
|
||||||
template <typename F> requires (CInvocableResult<ValueType, F, ValueType>)
|
template <typename F> requires (CInvocableResult<FValueType, F, FValueType>)
|
||||||
FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent)
|
FORCEINLINE FValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent)
|
||||||
{
|
{
|
||||||
ValueType Temp(Load(EMemoryOrder::Relaxed));
|
FValueType Temp(Load(EMemoryOrder::Relaxed));
|
||||||
// We do a weak read here because we require a loop.
|
// We do a weak read here because we require a loop.
|
||||||
while (!CompareExchange(Temp, InvokeResult<ValueType>(Forward<F>(Func), Temp), Order, true));
|
while (!CompareExchange(Temp, InvokeResult<FValueType>(Forward<F>(Func), Temp), Order, true));
|
||||||
return Temp;
|
return Temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Atomically executes the 'Func' on the value stored in the atomic object and obtains the value held previously. */
|
/** Atomically executes the 'Func' on the value stored in the atomic object and obtains the value held previously. */
|
||||||
template <typename F> requires (CInvocableResult<ValueType, F, ValueType> && bIsAlwaysLockFree)
|
template <typename F> requires (CInvocableResult<FValueType, F, FValueType> && bIsAlwaysLockFree)
|
||||||
FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile
|
FORCEINLINE FValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile
|
||||||
{
|
{
|
||||||
ValueType Temp(Load(EMemoryOrder::Relaxed));
|
FValueType Temp(Load(EMemoryOrder::Relaxed));
|
||||||
// We do a weak read here because we require a loop.
|
// We do a weak read here because we require a loop.
|
||||||
while (!CompareExchange(Temp, InvokeResult<ValueType>(Forward<F>(Func), Temp), Order, true));
|
while (!CompareExchange(Temp, InvokeResult<FValueType>(Forward<F>(Func), Temp), Order, true));
|
||||||
return Temp;
|
return Temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Atomically adds the argument to the value stored in the atomic object and obtains the value held previously. */
|
/** Atomically adds the argument to the value stored in the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchAdd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchAdd(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
FORCEINLINE ValueType FetchAdd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchAdd(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
|
||||||
/** Atomically adds the argument to the value stored in the atomic object and obtains the value held previously. */
|
/** Atomically adds the argument to the value stored in the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer<T> ) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer<T> ) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
FORCEINLINE ValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_add(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
|
||||||
/** Atomically subtracts the argument from the value stored in the atomic object and obtains the value held previously. */
|
/** Atomically subtracts the argument from the value stored in the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchSub(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchSub(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
FORCEINLINE ValueType FetchSub(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchSub(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
|
||||||
/** Atomically subtracts the argument from the value stored in the atomic object and obtains the value held previously. */
|
/** Atomically subtracts the argument from the value stored in the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer<T> ) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer<T> ) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
FORCEINLINE ValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_sub(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
|
||||||
/** Atomically multiples the argument from the value stored in the atomic object and obtains the value held previously. */
|
/** Atomically multiples the argument from the value stored in the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchMul(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old * InValue; }); }
|
FORCEINLINE FValueType FetchMul(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old * InValue; }); }
|
||||||
FORCEINLINE ValueType FetchMul(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return FetchFn([InValue](ValueType Old) -> ValueType { return Old * InValue; }); }
|
FORCEINLINE FValueType FetchMul(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return FetchFn([InValue](FValueType Old) -> FValueType { return Old * InValue; }); }
|
||||||
|
|
||||||
/** Atomically divides the argument from the value stored in the atomic object and obtains the value held previously. */
|
/** Atomically divides the argument from the value stored in the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchDiv(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old / InValue; }); }
|
FORCEINLINE FValueType FetchDiv(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> || CFloatingPoint<T>) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old / InValue; }); }
|
||||||
FORCEINLINE ValueType FetchDiv(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return FetchFn([InValue](ValueType Old) -> ValueType { return Old / InValue; }); }
|
FORCEINLINE FValueType FetchDiv(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree { return FetchFn([InValue](FValueType Old) -> FValueType { return Old / InValue; }); }
|
||||||
|
|
||||||
/** Atomically models the argument from the value stored in the atomic object and obtains the value held previously. */
|
/** Atomically models the argument from the value stored in the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchMod(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old % InValue; }); }
|
FORCEINLINE FValueType FetchMod(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old % InValue; }); }
|
||||||
FORCEINLINE ValueType FetchMod(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old % InValue; }); }
|
FORCEINLINE FValueType FetchMod(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old % InValue; }); }
|
||||||
|
|
||||||
/** Atomically performs bitwise AND between the argument and the value of the atomic object and obtains the value held previously. */
|
/** Atomically performs bitwise AND between the argument and the value of the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchAnd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_and(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchAnd(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_and(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
FORCEINLINE ValueType FetchAnd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_and(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchAnd(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_and(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
|
||||||
/** Atomically performs bitwise OR between the argument and the value of the atomic object and obtains the value held previously. */
|
/** Atomically performs bitwise OR between the argument and the value of the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchOr(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_or(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchOr(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_or(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
FORCEINLINE ValueType FetchOr(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_or(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchOr(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_or(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
|
||||||
/** Atomically performs bitwise XOR between the argument and the value of the atomic object and obtains the value held previously. */
|
/** Atomically performs bitwise XOR between the argument and the value of the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchXor(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_xor(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchXor(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return NativeAtomic.fetch_xor(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
FORCEINLINE ValueType FetchXor(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_xor(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE FValueType FetchXor(FValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic.fetch_xor(InValue, static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
|
||||||
/** Atomically performs bitwise LSH between the argument and the value of the atomic object and obtains the value held previously. */
|
/** Atomically performs bitwise LSH between the argument and the value of the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old << InValue; }); }
|
FORCEINLINE FValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old << InValue; }); }
|
||||||
FORCEINLINE ValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old << InValue; }); }
|
FORCEINLINE FValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old << InValue; }); }
|
||||||
|
|
||||||
/** Atomically performs bitwise RSH between the argument and the value of the atomic object and obtains the value held previously. */
|
/** Atomically performs bitwise RSH between the argument and the value of the atomic object and obtains the value held previously. */
|
||||||
FORCEINLINE ValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old >> InValue; }); }
|
FORCEINLINE FValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral<T> ) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old >> InValue; }); }
|
||||||
FORCEINLINE ValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old >> InValue; }); }
|
FORCEINLINE FValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchFn([InValue](FValueType Old) -> FValueType { return Old >> InValue; }); }
|
||||||
|
|
||||||
/** Increments the atomic value by one. */
|
/** Increments the atomic value by one. */
|
||||||
FORCEINLINE ValueType operator++() requires ((CIntegral<T> || CPointer<T>) ) { return ++NativeAtomic; }
|
FORCEINLINE FValueType operator++() requires ((CIntegral<T> || CPointer<T>) ) { return ++NativeAtomic; }
|
||||||
FORCEINLINE ValueType operator++() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return ++NativeAtomic; }
|
FORCEINLINE FValueType operator++() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return ++NativeAtomic; }
|
||||||
|
|
||||||
/** Increments the atomic value by one. */
|
/** Increments the atomic value by one. */
|
||||||
FORCEINLINE ValueType operator++(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic++; }
|
FORCEINLINE FValueType operator++(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic++; }
|
||||||
FORCEINLINE ValueType operator++(int) volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return NativeAtomic++; }
|
FORCEINLINE FValueType operator++(int) volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return NativeAtomic++; }
|
||||||
|
|
||||||
/** Decrements the atomic value by one. */
|
/** Decrements the atomic value by one. */
|
||||||
FORCEINLINE ValueType operator--() requires ((CIntegral<T> || CPointer<T>) ) { return --NativeAtomic; }
|
FORCEINLINE FValueType operator--() requires ((CIntegral<T> || CPointer<T>) ) { return --NativeAtomic; }
|
||||||
FORCEINLINE ValueType operator--() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return --NativeAtomic; }
|
FORCEINLINE FValueType operator--() volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return --NativeAtomic; }
|
||||||
|
|
||||||
/** Decrements the atomic value by one. */
|
/** Decrements the atomic value by one. */
|
||||||
FORCEINLINE ValueType operator--(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic--; }
|
FORCEINLINE FValueType operator--(int) requires ((CIntegral<T> || CPointer<T>) ) { return NativeAtomic--; }
|
||||||
FORCEINLINE ValueType operator--(int) volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return NativeAtomic--; }
|
FORCEINLINE FValueType operator--(int) volatile requires ((CIntegral<T> || CPointer<T>) && bIsAlwaysLockFree) { return NativeAtomic--; }
|
||||||
|
|
||||||
/** Adds with the atomic value. */
|
/** Adds with the atomic value. */
|
||||||
FORCEINLINE ValueType operator+=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic += InValue; }
|
FORCEINLINE FValueType operator+=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic += InValue; }
|
||||||
FORCEINLINE ValueType operator+=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic += InValue; }
|
FORCEINLINE FValueType operator+=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic += InValue; }
|
||||||
|
|
||||||
/** Adds with the atomic value. */
|
/** Adds with the atomic value. */
|
||||||
FORCEINLINE ValueType operator+=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic += InValue; }
|
FORCEINLINE FValueType operator+=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic += InValue; }
|
||||||
FORCEINLINE ValueType operator+=(ptrdiff InValue) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic += InValue; }
|
FORCEINLINE FValueType operator+=(ptrdiff InValue) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic += InValue; }
|
||||||
|
|
||||||
/** Subtracts with the atomic value. */
|
/** Subtracts with the atomic value. */
|
||||||
FORCEINLINE ValueType operator-=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic -= InValue; }
|
FORCEINLINE FValueType operator-=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return NativeAtomic -= InValue; }
|
||||||
FORCEINLINE ValueType operator-=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
|
FORCEINLINE FValueType operator-=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
|
||||||
|
|
||||||
/** Subtracts with the atomic value. */
|
/** Subtracts with the atomic value. */
|
||||||
FORCEINLINE ValueType operator-=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic -= InValue; }
|
FORCEINLINE FValueType operator-=(ptrdiff InValue) requires (CPointer<T> ) { return NativeAtomic -= InValue; }
|
||||||
FORCEINLINE ValueType operator-=(ptrdiff InValue) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
|
FORCEINLINE FValueType operator-=(ptrdiff InValue) volatile requires (CPointer<T> && bIsAlwaysLockFree) { return NativeAtomic -= InValue; }
|
||||||
|
|
||||||
/** Multiples with the atomic value. */
|
/** Multiples with the atomic value. */
|
||||||
FORCEINLINE ValueType operator*=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchMul(InValue) * InValue; }
|
FORCEINLINE FValueType operator*=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchMul(InValue) * InValue; }
|
||||||
FORCEINLINE ValueType operator*=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchMul(InValue) * InValue; }
|
FORCEINLINE FValueType operator*=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchMul(InValue) * InValue; }
|
||||||
|
|
||||||
/** Divides with the atomic value. */
|
/** Divides with the atomic value. */
|
||||||
FORCEINLINE ValueType operator/=(ValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchDiv(InValue) / InValue; }
|
FORCEINLINE FValueType operator/=(FValueType InValue) requires ((CIntegral<T> || CFloatingPoint<T>) ) { return FetchDiv(InValue) / InValue; }
|
||||||
FORCEINLINE ValueType operator/=(ValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchDiv(InValue) / InValue; }
|
FORCEINLINE FValueType operator/=(FValueType InValue) volatile requires ((CIntegral<T> || CFloatingPoint<T>) && bIsAlwaysLockFree) { return FetchDiv(InValue) / InValue; }
|
||||||
|
|
||||||
/** Models with the atomic value. */
|
/** Models with the atomic value. */
|
||||||
FORCEINLINE ValueType operator%=(ValueType InValue) requires (CIntegral<T> ) { return FetchMod(InValue) % InValue; }
|
FORCEINLINE FValueType operator%=(FValueType InValue) requires (CIntegral<T> ) { return FetchMod(InValue) % InValue; }
|
||||||
FORCEINLINE ValueType operator%=(ValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchMod(InValue) % InValue; }
|
FORCEINLINE FValueType operator%=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchMod(InValue) % InValue; }
|
||||||
|
|
||||||
/** Performs bitwise AND with the atomic value. */
|
/** Performs bitwise AND with the atomic value. */
|
||||||
FORCEINLINE ValueType operator&=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic &= InValue; }
|
FORCEINLINE FValueType operator&=(FValueType InValue) requires (CIntegral<T> ) { return NativeAtomic &= InValue; }
|
||||||
FORCEINLINE ValueType operator&=(ValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic &= InValue; }
|
FORCEINLINE FValueType operator&=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic &= InValue; }
|
||||||
|
|
||||||
/** Performs bitwise OR with the atomic value. */
|
/** Performs bitwise OR with the atomic value. */
|
||||||
FORCEINLINE ValueType operator|=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic |= InValue; }
|
FORCEINLINE FValueType operator|=(FValueType InValue) requires (CIntegral<T> ) { return NativeAtomic |= InValue; }
|
||||||
FORCEINLINE ValueType operator|=(ValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic |= InValue; }
|
FORCEINLINE FValueType operator|=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic |= InValue; }
|
||||||
|
|
||||||
/** Performs bitwise XOR with the atomic value. */
|
/** Performs bitwise XOR with the atomic value. */
|
||||||
FORCEINLINE ValueType operator^=(ValueType InValue) requires (CIntegral<T> ) { return NativeAtomic ^= InValue; }
|
FORCEINLINE FValueType operator^=(FValueType InValue) requires (CIntegral<T> ) { return NativeAtomic ^= InValue; }
|
||||||
FORCEINLINE ValueType operator^=(ValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic ^= InValue; }
|
FORCEINLINE FValueType operator^=(FValueType InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return NativeAtomic ^= InValue; }
|
||||||
|
|
||||||
/** Performs bitwise LSH with the atomic value. */
|
/** Performs bitwise LSH with the atomic value. */
|
||||||
FORCEINLINE ValueType operator<<=(size_t InValue) requires (CIntegral<T> ) { return FetchLsh(InValue) << InValue; }
|
FORCEINLINE FValueType operator<<=(size_t InValue) requires (CIntegral<T> ) { return FetchLsh(InValue) << InValue; }
|
||||||
FORCEINLINE ValueType operator<<=(size_t InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchLsh(InValue) << InValue; }
|
FORCEINLINE FValueType operator<<=(size_t InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchLsh(InValue) << InValue; }
|
||||||
|
|
||||||
/** Performs bitwise RSH with the atomic value. */
|
/** Performs bitwise RSH with the atomic value. */
|
||||||
FORCEINLINE ValueType operator>>=(size_t InValue) requires (CIntegral<T> ) { return FetchRsh(InValue) >> InValue; }
|
FORCEINLINE FValueType operator>>=(size_t InValue) requires (CIntegral<T> ) { return FetchRsh(InValue) >> InValue; }
|
||||||
FORCEINLINE ValueType operator>>=(size_t InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchRsh(InValue) >> InValue; }
|
FORCEINLINE FValueType operator>>=(size_t InValue) volatile requires (CIntegral<T> && bIsAlwaysLockFree) { return FetchRsh(InValue) >> InValue; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
NativeAtomicType NativeAtomic;
|
FNativeAtomic NativeAtomic;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ struct FAtomicFlag final : FSingleton
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/** Constructs an atomic flag. */
|
/** Constructs an atomic flag. */
|
||||||
FORCEINLINE constexpr FAtomicFlag() : NativeAtomic() { };
|
FORCEINLINE constexpr FAtomicFlag() = default;
|
||||||
|
|
||||||
/** Atomically sets flag to false. */
|
/** Atomically sets flag to false. */
|
||||||
FORCEINLINE void Clear(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.clear(static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
FORCEINLINE void Clear(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.clear(static_cast<NAMESPACE_STD::memory_order>(Order)); }
|
||||||
|
@ -262,29 +262,29 @@ public:
|
|||||||
{
|
{
|
||||||
Callable = InCallable;
|
Callable = InCallable;
|
||||||
|
|
||||||
using DecayedType = TDecay<T>;
|
using FDecayedType = TDecay<T>;
|
||||||
|
|
||||||
static constexpr const FRTTI SelectedRTTI(InPlaceType<DecayedType>);
|
static constexpr const FRTTI SelectedRTTI(InPlaceType<FDecayedType>);
|
||||||
RTTI = reinterpret_cast<uintptr>(&SelectedRTTI);
|
RTTI = reinterpret_cast<uintptr>(&SelectedRTTI);
|
||||||
|
|
||||||
if constexpr (CEmpty<DecayedType> && CTrivial<DecayedType>) return; // ERepresentation::Empty
|
if constexpr (CEmpty<FDecayedType> && CTrivial<FDecayedType>) return; // ERepresentation::Empty
|
||||||
|
|
||||||
constexpr bool bIsTriviallyStorable = sizeof(DecayedType) <= sizeof(InternalStorage) && alignof(DecayedType) <= alignof(TFunctionStorage) && CTriviallyCopyable<DecayedType>;
|
constexpr bool bIsTriviallyStorable = sizeof(FDecayedType) <= sizeof(InternalStorage) && alignof(FDecayedType) <= alignof(TFunctionStorage) && CTriviallyCopyable<FDecayedType>;
|
||||||
constexpr bool bIsSmallStorable = sizeof(DecayedType) <= sizeof(InternalStorage) && alignof(DecayedType) <= alignof(TFunctionStorage);
|
constexpr bool bIsSmallStorable = sizeof(FDecayedType) <= sizeof(InternalStorage) && alignof(FDecayedType) <= alignof(TFunctionStorage);
|
||||||
|
|
||||||
if constexpr (bIsTriviallyStorable)
|
if constexpr (bIsTriviallyStorable)
|
||||||
{
|
{
|
||||||
new (&InternalStorage) DecayedType(Forward<Ts>(Args)...);
|
new (&InternalStorage) FDecayedType(Forward<Ts>(Args)...);
|
||||||
RTTI |= static_cast<uintptr>(ERepresentation::Trivial);
|
RTTI |= static_cast<uintptr>(ERepresentation::Trivial);
|
||||||
}
|
}
|
||||||
else if constexpr (bIsSmallStorable)
|
else if constexpr (bIsSmallStorable)
|
||||||
{
|
{
|
||||||
new (&InternalStorage) DecayedType(Forward<Ts>(Args)...);
|
new (&InternalStorage) FDecayedType(Forward<Ts>(Args)...);
|
||||||
RTTI |= static_cast<uintptr>(ERepresentation::Small);
|
RTTI |= static_cast<uintptr>(ERepresentation::Small);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExternalStorage = new DecayedType(Forward<Ts>(Args)...);
|
ExternalStorage = new FDecayedType(Forward<Ts>(Args)...);
|
||||||
RTTI |= static_cast<uintptr>(ERepresentation::Big);
|
RTTI |= static_cast<uintptr>(ERepresentation::Big);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,12 +446,12 @@ template <typename Ret, typename... Ts, typename F> struct TIsInvocableSignature
|
|||||||
template <typename Ret, typename... Ts, typename F> struct TIsInvocableSignature<Ret(Ts...) const&&, F> : TBoolConstant<CInvocableResult<Ret, const F , Ts...>> { };
|
template <typename Ret, typename... Ts, typename F> struct TIsInvocableSignature<Ret(Ts...) const&&, F> : TBoolConstant<CInvocableResult<Ret, const F , Ts...>> { };
|
||||||
|
|
||||||
template <typename F> struct TFunctionInfo;
|
template <typename F> struct TFunctionInfo;
|
||||||
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) > { using Fn = Ret(Ts...); using CVRef = int; };
|
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) > { using FFn = Ret(Ts...); using FCVRef = int; };
|
||||||
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) & > { using Fn = Ret(Ts...); using CVRef = int&; };
|
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) & > { using FFn = Ret(Ts...); using FCVRef = int&; };
|
||||||
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) && > { using Fn = Ret(Ts...); using CVRef = int&&; };
|
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) && > { using FFn = Ret(Ts...); using FCVRef = int&&; };
|
||||||
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const > { using Fn = Ret(Ts...); using CVRef = const int; };
|
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const > { using FFn = Ret(Ts...); using FCVRef = const int; };
|
||||||
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const& > { using Fn = Ret(Ts...); using CVRef = const int&; };
|
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const& > { using FFn = Ret(Ts...); using FCVRef = const int&; };
|
||||||
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const&&> { using Fn = Ret(Ts...); using CVRef = const int&&; };
|
template <typename Ret, typename... Ts> struct TFunctionInfo<Ret(Ts...) const&&> { using FFn = Ret(Ts...); using FCVRef = const int&&; };
|
||||||
|
|
||||||
template <typename F, typename CVRef, bool bIsRef, bool bIsUnique = false> class TFunctionImpl;
|
template <typename F, typename CVRef, bool bIsRef, bool bIsUnique = false> class TFunctionImpl;
|
||||||
|
|
||||||
@ -460,8 +460,8 @@ class TFunctionImpl<Ret(Ts...), CVRef, bIsRef, bIsUnique>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ResultType = Ret;
|
using FResultType = Ret;
|
||||||
using ArgumentType = TTypeSequence<Ts...>;
|
using FArgumentType = TTypeSequence<Ts...>;
|
||||||
|
|
||||||
FORCEINLINE constexpr TFunctionImpl() = default;
|
FORCEINLINE constexpr TFunctionImpl() = default;
|
||||||
FORCEINLINE constexpr TFunctionImpl(const TFunctionImpl&) = default;
|
FORCEINLINE constexpr TFunctionImpl(const TFunctionImpl&) = default;
|
||||||
@ -471,12 +471,12 @@ public:
|
|||||||
FORCEINLINE constexpr ~TFunctionImpl() = default;
|
FORCEINLINE constexpr ~TFunctionImpl() = default;
|
||||||
|
|
||||||
/** Invokes the stored callable function target with the parameters args. */
|
/** Invokes the stored callable function target with the parameters args. */
|
||||||
FORCEINLINE ResultType operator()(Ts... Args) requires (CSameAs<CVRef, int >) { return CallImpl(Forward<Ts>(Args)...); }
|
FORCEINLINE FResultType operator()(Ts... Args) requires (CSameAs<CVRef, int >) { return CallImpl(Forward<Ts>(Args)...); }
|
||||||
FORCEINLINE ResultType operator()(Ts... Args) & requires (CSameAs<CVRef, int& >) { return CallImpl(Forward<Ts>(Args)...); }
|
FORCEINLINE FResultType operator()(Ts... Args) & requires (CSameAs<CVRef, int& >) { return CallImpl(Forward<Ts>(Args)...); }
|
||||||
FORCEINLINE ResultType operator()(Ts... Args) && requires (CSameAs<CVRef, int&&>) { return CallImpl(Forward<Ts>(Args)...); }
|
FORCEINLINE FResultType operator()(Ts... Args) && requires (CSameAs<CVRef, int&&>) { return CallImpl(Forward<Ts>(Args)...); }
|
||||||
FORCEINLINE ResultType operator()(Ts... Args) const requires (CSameAs<CVRef, const int >) { return CallImpl(Forward<Ts>(Args)...); }
|
FORCEINLINE FResultType operator()(Ts... Args) const requires (CSameAs<CVRef, const int >) { return CallImpl(Forward<Ts>(Args)...); }
|
||||||
FORCEINLINE ResultType operator()(Ts... Args) const& requires (CSameAs<CVRef, const int& >) { return CallImpl(Forward<Ts>(Args)...); }
|
FORCEINLINE FResultType operator()(Ts... Args) const& requires (CSameAs<CVRef, const int& >) { return CallImpl(Forward<Ts>(Args)...); }
|
||||||
FORCEINLINE ResultType operator()(Ts... Args) const&& requires (CSameAs<CVRef, const int&&>) { return CallImpl(Forward<Ts>(Args)...); }
|
FORCEINLINE FResultType operator()(Ts... Args) const&& requires (CSameAs<CVRef, const int&&>) { return CallImpl(Forward<Ts>(Args)...); }
|
||||||
|
|
||||||
/** @return false if instance stores a callable function target, true otherwise. */
|
/** @return false if instance stores a callable function target, true otherwise. */
|
||||||
NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& requires (!bIsRef) { return !IsValid(); }
|
NODISCARD FORCEINLINE constexpr bool operator==(nullptr_t) const& requires (!bIsRef) { return !IsValid(); }
|
||||||
@ -487,14 +487,14 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using CallableType = ResultType(*)(uintptr, Ts&&...);
|
using FCallableType = FResultType(*)(uintptr, Ts&&...);
|
||||||
|
|
||||||
TFunctionStorage<bIsRef, bIsUnique> Storage;
|
TFunctionStorage<bIsRef, bIsUnique> Storage;
|
||||||
|
|
||||||
FORCEINLINE ResultType CallImpl(Ts&&... Args) const
|
FORCEINLINE FResultType CallImpl(Ts&&... Args) const
|
||||||
{
|
{
|
||||||
checkf(Storage.IsValid(), TEXT("Attempting to call an unbound TFunction!"));
|
checkf(Storage.IsValid(), TEXT("Attempting to call an unbound TFunction!"));
|
||||||
CallableType Callable = reinterpret_cast<CallableType>(Storage.GetCallable());
|
FCallableType Callable = reinterpret_cast<FCallableType>(Storage.GetCallable());
|
||||||
return Callable(Storage.GetValuePtr(), Forward<Ts>(Args)...);
|
return Callable(Storage.GetValuePtr(), Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,26 +510,26 @@ protected:
|
|||||||
template <typename T, typename... Us>
|
template <typename T, typename... Us>
|
||||||
FORCEINLINE constexpr TDecay<T>& Emplace(Us&&... Args)
|
FORCEINLINE constexpr TDecay<T>& Emplace(Us&&... Args)
|
||||||
{
|
{
|
||||||
using DecayedType = TDecay<T>;
|
using FDecayedType = TDecay<T>;
|
||||||
|
|
||||||
// This add a l-value reference to a non-reference type, while preserving the r-value reference.
|
// This add a l-value reference to a non-reference type, while preserving the r-value reference.
|
||||||
using ObjectType = TCopyCVRef<CVRef, DecayedType>;
|
using FObjectType = TCopyCVRef<CVRef, FDecayedType>;
|
||||||
using InvokeType = TConditional<CReference<ObjectType>, ObjectType, ObjectType&>;
|
using FInvokeType = TConditional<CReference<FObjectType>, FObjectType, FObjectType&>;
|
||||||
|
|
||||||
CallableType Callable = [](uintptr ObjectPtr, Ts&&... Args) -> ResultType
|
FCallableType Callable = [](uintptr ObjectPtr, Ts&&... Args) -> FResultType
|
||||||
{
|
{
|
||||||
return InvokeResult<ResultType>(
|
return InvokeResult<FResultType>(
|
||||||
static_cast<InvokeType>(*reinterpret_cast<DecayedType*>(ObjectPtr)),
|
static_cast<FInvokeType>(*reinterpret_cast<FDecayedType*>(ObjectPtr)),
|
||||||
Forward<Ts>(Args)...
|
Forward<Ts>(Args)...
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Storage.template Emplace<DecayedType>(
|
Storage.template Emplace<FDecayedType>(
|
||||||
reinterpret_cast<uintptr>(Callable),
|
reinterpret_cast<uintptr>(Callable),
|
||||||
Forward<Us>(Args)...
|
Forward<Us>(Args)...
|
||||||
);
|
);
|
||||||
|
|
||||||
return *reinterpret_cast<DecayedType*>(Storage.GetValuePtr());
|
return *reinterpret_cast<FDecayedType*>(Storage.GetValuePtr());
|
||||||
}
|
}
|
||||||
|
|
||||||
friend FORCEINLINE constexpr void Swap(TFunctionImpl& A, TFunctionImpl& B) requires (!bIsRef) { Swap(A.Storage, B.Storage); }
|
friend FORCEINLINE constexpr void Swap(TFunctionImpl& A, TFunctionImpl& B) requires (!bIsRef) { Swap(A.Storage, B.Storage); }
|
||||||
@ -552,15 +552,15 @@ NAMESPACE_PRIVATE_END
|
|||||||
template <CFunction F>
|
template <CFunction F>
|
||||||
class TFunctionRef final
|
class TFunctionRef final
|
||||||
: public NAMESPACE_PRIVATE::TFunctionImpl<
|
: public NAMESPACE_PRIVATE::TFunctionImpl<
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
|
||||||
true>
|
true>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Impl = NAMESPACE_PRIVATE::TFunctionImpl<
|
using FImpl = NAMESPACE_PRIVATE::TFunctionImpl<
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
|
||||||
true>;
|
true>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -585,7 +585,7 @@ public:
|
|||||||
FORCEINLINE constexpr TFunctionRef(T&& InValue)
|
FORCEINLINE constexpr TFunctionRef(T&& InValue)
|
||||||
{
|
{
|
||||||
checkf(NAMESPACE_PRIVATE::FunctionIsBound(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef"));
|
checkf(NAMESPACE_PRIVATE::FunctionIsBound(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef"));
|
||||||
Impl::template Emplace<T>(Forward<T>(InValue));
|
FImpl::template Emplace<T>(Forward<T>(InValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -602,21 +602,21 @@ public:
|
|||||||
template <CFunction F>
|
template <CFunction F>
|
||||||
class TFunction final
|
class TFunction final
|
||||||
: public NAMESPACE_PRIVATE::TFunctionImpl<
|
: public NAMESPACE_PRIVATE::TFunctionImpl<
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
|
||||||
false, false>
|
false, false>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Impl = NAMESPACE_PRIVATE::TFunctionImpl<
|
using FImpl = NAMESPACE_PRIVATE::TFunctionImpl<
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
|
||||||
false, false>;
|
false, false>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Default constructor. */
|
/** Default constructor. */
|
||||||
FORCEINLINE constexpr TFunction(nullptr_t = nullptr) { Impl::Invalidate(); }
|
FORCEINLINE constexpr TFunction(nullptr_t = nullptr) { FImpl::Invalidate(); }
|
||||||
|
|
||||||
FORCEINLINE TFunction(const TFunction&) = default;
|
FORCEINLINE TFunction(const TFunction&) = default;
|
||||||
FORCEINLINE TFunction(TFunction&&) = default;
|
FORCEINLINE TFunction(TFunction&&) = default;
|
||||||
@ -634,8 +634,8 @@ public:
|
|||||||
&& NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value)
|
&& NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value)
|
||||||
FORCEINLINE TFunction(T&& InValue)
|
FORCEINLINE TFunction(T&& InValue)
|
||||||
{
|
{
|
||||||
if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Impl::Invalidate();
|
if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) FImpl::Invalidate();
|
||||||
else Impl::template Emplace<T>(Forward<T>(InValue));
|
else FImpl::template Emplace<T>(Forward<T>(InValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -647,7 +647,7 @@ public:
|
|||||||
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
||||||
FORCEINLINE explicit TFunction(TInPlaceType<T>, Ts&&... Args)
|
FORCEINLINE explicit TFunction(TInPlaceType<T>, Ts&&... Args)
|
||||||
{
|
{
|
||||||
Impl::template Emplace<T>(Forward<Ts>(Args)...);
|
FImpl::template Emplace<T>(Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -659,7 +659,7 @@ public:
|
|||||||
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
||||||
FORCEINLINE explicit TFunction(TInPlaceType<T>, initializer_list<U> IL, Ts&&... Args)
|
FORCEINLINE explicit TFunction(TInPlaceType<T>, initializer_list<U> IL, Ts&&... Args)
|
||||||
{
|
{
|
||||||
Impl::template Emplace<T>(IL, Forward<Ts>(Args)...);
|
FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes any bound callable from the TFunction, restoring it to the default empty state. */
|
/** Removes any bound callable from the TFunction, restoring it to the default empty state. */
|
||||||
@ -692,8 +692,8 @@ public:
|
|||||||
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
||||||
FORCEINLINE TDecay<T>& Emplace(Ts&&... Args)
|
FORCEINLINE TDecay<T>& Emplace(Ts&&... Args)
|
||||||
{
|
{
|
||||||
Impl::Destroy();
|
FImpl::Destroy();
|
||||||
return Impl::template Emplace<T>(Forward<Ts>(Args)...);
|
return FImpl::template Emplace<T>(Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -710,15 +710,15 @@ public:
|
|||||||
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
&& CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
||||||
FORCEINLINE TDecay<T>& Emplace(initializer_list<U> IL, Ts&&... Args)
|
FORCEINLINE TDecay<T>& Emplace(initializer_list<U> IL, Ts&&... Args)
|
||||||
{
|
{
|
||||||
Impl::Destroy();
|
FImpl::Destroy();
|
||||||
return Impl::template Emplace<T>(IL, Forward<Ts>(Args)...);
|
return FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes any bound callable from the TFunction, restoring it to the default empty state. */
|
/** Removes any bound callable from the TFunction, restoring it to the default empty state. */
|
||||||
FORCEINLINE constexpr void Reset() { Impl::Destroy(); Impl::Invalidate(); }
|
FORCEINLINE constexpr void Reset() { FImpl::Destroy(); FImpl::Invalidate(); }
|
||||||
|
|
||||||
/** Overloads the Swap algorithm for TFunction. */
|
/** Overloads the Swap algorithm for TFunction. */
|
||||||
friend FORCEINLINE constexpr void Swap(TFunction& A, TFunction& B) { Swap(static_cast<Impl&>(A), static_cast<Impl&>(B)); }
|
friend FORCEINLINE constexpr void Swap(TFunction& A, TFunction& B) { Swap(static_cast<FImpl&>(A), static_cast<FImpl&>(B)); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -731,21 +731,21 @@ public:
|
|||||||
template <CFunction F>
|
template <CFunction F>
|
||||||
class TUniqueFunction final
|
class TUniqueFunction final
|
||||||
: public NAMESPACE_PRIVATE::TFunctionImpl<
|
: public NAMESPACE_PRIVATE::TFunctionImpl<
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
|
||||||
false, true>
|
false, true>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Impl = NAMESPACE_PRIVATE::TFunctionImpl<
|
using FImpl = NAMESPACE_PRIVATE::TFunctionImpl<
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FFn,
|
||||||
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef,
|
typename NAMESPACE_PRIVATE::TFunctionInfo<F>::FCVRef,
|
||||||
false, true>;
|
false, true>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Default constructor. */
|
/** Default constructor. */
|
||||||
FORCEINLINE constexpr TUniqueFunction(nullptr_t = nullptr) { Impl::Invalidate(); }
|
FORCEINLINE constexpr TUniqueFunction(nullptr_t = nullptr) { FImpl::Invalidate(); }
|
||||||
|
|
||||||
FORCEINLINE TUniqueFunction(const TUniqueFunction&) = delete;
|
FORCEINLINE TUniqueFunction(const TUniqueFunction&) = delete;
|
||||||
FORCEINLINE TUniqueFunction(TUniqueFunction&&) = default;
|
FORCEINLINE TUniqueFunction(TUniqueFunction&&) = default;
|
||||||
@ -788,8 +788,8 @@ public:
|
|||||||
&& NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value)
|
&& NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value)
|
||||||
FORCEINLINE TUniqueFunction(T&& InValue)
|
FORCEINLINE TUniqueFunction(T&& InValue)
|
||||||
{
|
{
|
||||||
if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Impl::Invalidate();
|
if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) FImpl::Invalidate();
|
||||||
else Impl::template Emplace<T>(Forward<T>(InValue));
|
else FImpl::template Emplace<T>(Forward<T>(InValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -800,7 +800,7 @@ public:
|
|||||||
&& CConstructibleFrom<TDecay<T>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
&& CConstructibleFrom<TDecay<T>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
||||||
FORCEINLINE explicit TUniqueFunction(TInPlaceType<T>, Ts&&... Args)
|
FORCEINLINE explicit TUniqueFunction(TInPlaceType<T>, Ts&&... Args)
|
||||||
{
|
{
|
||||||
Impl::template Emplace<T>(Forward<Ts>(Args)...);
|
FImpl::template Emplace<T>(Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -811,11 +811,11 @@ public:
|
|||||||
&& CConstructibleFrom<TDecay<T>, initializer_list<U>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
&& CConstructibleFrom<TDecay<T>, initializer_list<U>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
||||||
FORCEINLINE explicit TUniqueFunction(TInPlaceType<T>, initializer_list<U> IL, Ts&&... Args)
|
FORCEINLINE explicit TUniqueFunction(TInPlaceType<T>, initializer_list<U> IL, Ts&&... Args)
|
||||||
{
|
{
|
||||||
Impl::template Emplace<T>(IL, Forward<Ts>(Args)...);
|
FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes any bound callable from the TUniqueFunction, restoring it to the default empty state. */
|
/** Removes any bound callable from the TUniqueFunction, restoring it to the default empty state. */
|
||||||
FORCEINLINE constexpr TUniqueFunction& operator=(nullptr_t) { Impl::Destroy(); Impl::Invalidate(); return *this; }
|
FORCEINLINE constexpr TUniqueFunction& operator=(nullptr_t) { FImpl::Destroy(); FImpl::Invalidate(); return *this; }
|
||||||
|
|
||||||
template <typename T> requires (NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value
|
template <typename T> requires (NAMESPACE_PRIVATE::TIsInvocableSignature<F, TDecay<T>>::Value
|
||||||
&& !CTFunctionRef<TDecay<T>> && !CTFunction<TDecay<T>> && !CTUniqueFunction<TDecay<T>>
|
&& !CTFunctionRef<TDecay<T>> && !CTFunction<TDecay<T>> && !CTUniqueFunction<TDecay<T>>
|
||||||
@ -841,9 +841,9 @@ public:
|
|||||||
&& CConstructibleFrom<TDecay<T>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
&& CConstructibleFrom<TDecay<T>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
||||||
FORCEINLINE TDecay<T>& Emplace(Ts&&... Args)
|
FORCEINLINE TDecay<T>& Emplace(Ts&&... Args)
|
||||||
{
|
{
|
||||||
Impl::Destroy();
|
FImpl::Destroy();
|
||||||
using DecayedType = TDecay<T>;
|
|
||||||
return Impl::template Emplace<T>(Forward<Ts>(Args)...);
|
return FImpl::template Emplace<T>(Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -859,16 +859,16 @@ public:
|
|||||||
&& CConstructibleFrom<TDecay<T>, initializer_list<U>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
&& CConstructibleFrom<TDecay<T>, initializer_list<U>, Ts...> && CMoveConstructible<TDecay<T>> && CDestructible<TDecay<T>>)
|
||||||
FORCEINLINE TDecay<T>& Emplace(initializer_list<U> IL, Ts&&... Args)
|
FORCEINLINE TDecay<T>& Emplace(initializer_list<U> IL, Ts&&... Args)
|
||||||
{
|
{
|
||||||
Impl::Destroy();
|
FImpl::Destroy();
|
||||||
using DecayedType = TDecay<T>;
|
|
||||||
return Impl::template Emplace<T>(IL, Forward<Ts>(Args)...);
|
return FImpl::template Emplace<T>(IL, Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes any bound callable from the TUniqueFunction, restoring it to the default empty state. */
|
/** Removes any bound callable from the TUniqueFunction, restoring it to the default empty state. */
|
||||||
FORCEINLINE constexpr void Reset() { Impl::Destroy(); Impl::Invalidate(); }
|
FORCEINLINE constexpr void Reset() { FImpl::Destroy(); FImpl::Invalidate(); }
|
||||||
|
|
||||||
/** Overloads the Swap algorithm for TUniqueFunction. */
|
/** Overloads the Swap algorithm for TUniqueFunction. */
|
||||||
friend FORCEINLINE constexpr void Swap(TUniqueFunction& A, TUniqueFunction& B) { Swap(static_cast<Impl&>(A), static_cast<Impl&>(B)); }
|
friend FORCEINLINE constexpr void Swap(TUniqueFunction& A, TUniqueFunction& B) { Swap(static_cast<FImpl&>(A), static_cast<FImpl&>(B)); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
|
|||||||
|
|
||||||
NAMESPACE_PRIVATE_BEGIN
|
NAMESPACE_PRIVATE_BEGIN
|
||||||
|
|
||||||
struct InvokeFunction
|
struct FInvokeFunction
|
||||||
{
|
{
|
||||||
template <typename F, typename... Ts>
|
template <typename F, typename... Ts>
|
||||||
static auto Invoke(F&& Object, Ts&&... Args)
|
static auto Invoke(F&& Object, Ts&&... Args)
|
||||||
@ -20,7 +20,7 @@ struct InvokeFunction
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InvokeMemberFunction
|
struct FInvokeMemberFunction
|
||||||
{
|
{
|
||||||
template <typename F, typename ObjectType, typename... Ts>
|
template <typename F, typename ObjectType, typename... Ts>
|
||||||
static auto Invoke(F&& Func, ObjectType&& Object, Ts&&... Args)
|
static auto Invoke(F&& Func, ObjectType&& Object, Ts&&... Args)
|
||||||
@ -37,7 +37,7 @@ struct InvokeMemberFunction
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InvokeMemberObject
|
struct FInvokeMemberObject
|
||||||
{
|
{
|
||||||
template <typename F, typename ObjectType>
|
template <typename F, typename ObjectType>
|
||||||
static auto Invoke(F&& Func, ObjectType&& Object)
|
static auto Invoke(F&& Func, ObjectType&& Object)
|
||||||
@ -59,34 +59,34 @@ template <typename F,
|
|||||||
typename Decayed = TDecay<F>,
|
typename Decayed = TDecay<F>,
|
||||||
bool IsMemberFunction = CMemberFunctionPointer<Decayed>,
|
bool IsMemberFunction = CMemberFunctionPointer<Decayed>,
|
||||||
bool IsMemberObject = CMemberObjectPointer<Decayed>>
|
bool IsMemberObject = CMemberObjectPointer<Decayed>>
|
||||||
struct InvokeMember;
|
struct FInvokeMember;
|
||||||
|
|
||||||
template <typename F, typename T, typename Decayed>
|
template <typename F, typename T, typename Decayed>
|
||||||
struct InvokeMember<F, T, Decayed, true, false> : InvokeMemberFunction { };
|
struct FInvokeMember<F, T, Decayed, true, false> : FInvokeMemberFunction { };
|
||||||
|
|
||||||
template <typename F, typename T, typename Decayed>
|
template <typename F, typename T, typename Decayed>
|
||||||
struct InvokeMember<F, T, Decayed, false, true> : InvokeMemberObject { };
|
struct FInvokeMember<F, T, Decayed, false, true> : FInvokeMemberObject { };
|
||||||
|
|
||||||
template <typename F, typename T, typename Decayed>
|
template <typename F, typename T, typename Decayed>
|
||||||
struct InvokeMember<F, T, Decayed, false, false> : InvokeFunction { };
|
struct FInvokeMember<F, T, Decayed, false, false> : FInvokeFunction { };
|
||||||
|
|
||||||
template <typename F, typename... Ts>
|
template <typename F, typename... Ts>
|
||||||
struct InvokeImpl;
|
struct FInvokeImpl;
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
struct InvokeImpl<F> : InvokeFunction { };
|
struct FInvokeImpl<F> : FInvokeFunction { };
|
||||||
|
|
||||||
template <typename F, typename T, typename... Ts>
|
template <typename F, typename T, typename... Ts>
|
||||||
struct InvokeImpl<F, T, Ts...> : InvokeMember<F, T> { };
|
struct FInvokeImpl<F, T, Ts...> : FInvokeMember<F, T> { };
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
/** Invoke the Callable object f with the parameters args. */
|
/** Invoke the Callable object f with the parameters args. */
|
||||||
template <typename F, typename... Ts> requires (CInvocable<F, Ts...>)
|
template <typename F, typename... Ts> requires (CInvocable<F, Ts...>)
|
||||||
FORCEINLINE constexpr auto Invoke(F&& Func, Ts&&... Args)
|
FORCEINLINE constexpr auto Invoke(F&& Func, Ts&&... Args)
|
||||||
-> decltype(NAMESPACE_PRIVATE::InvokeImpl<F, Ts...>::Invoke(Forward<F>(Func), Forward<Ts>(Args)...))
|
-> decltype(NAMESPACE_PRIVATE::FInvokeImpl<F, Ts...>::Invoke(Forward<F>(Func), Forward<Ts>(Args)...))
|
||||||
{
|
{
|
||||||
return NAMESPACE_PRIVATE::InvokeImpl<F, Ts...>::Invoke(Forward<F>(Func), Forward<Ts>(Args)...);
|
return NAMESPACE_PRIVATE::FInvokeImpl<F, Ts...>::Invoke(Forward<F>(Func), Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Invoke the Callable object f with the parameters args. */
|
/** Invoke the Callable object f with the parameters args. */
|
||||||
|
@ -12,7 +12,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
|
|||||||
template <typename T, T... Ints>
|
template <typename T, T... Ints>
|
||||||
struct TIntegerSequence
|
struct TIntegerSequence
|
||||||
{
|
{
|
||||||
using ValueType = T;
|
using FValueType = T;
|
||||||
FORCEINLINE static constexpr size_t Num() { return sizeof...(Ints); }
|
FORCEINLINE static constexpr size_t Num() { return sizeof...(Ints); }
|
||||||
FORCEINLINE static constexpr const T* GetData() { return NAMESPACE_REDCRAFT::GetData({ Ints... }); }
|
FORCEINLINE static constexpr const T* GetData() { return NAMESPACE_REDCRAFT::GetData({ Ints... }); }
|
||||||
};
|
};
|
||||||
@ -24,7 +24,7 @@ NAMESPACE_PRIVATE_BEGIN
|
|||||||
template <unsigned N, typename T>
|
template <unsigned N, typename T>
|
||||||
struct TMakeIntegerSequenceImpl
|
struct TMakeIntegerSequenceImpl
|
||||||
{
|
{
|
||||||
using Type = typename __make_integer_seq<TIntegerSequence, T, N>;
|
using FType = typename __make_integer_seq<TIntegerSequence, T, N>;
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif __has_builtin(__make_integer_seq)
|
#elif __has_builtin(__make_integer_seq)
|
||||||
@ -32,7 +32,7 @@ struct TMakeIntegerSequenceImpl
|
|||||||
template <unsigned N, typename T>
|
template <unsigned N, typename T>
|
||||||
struct TMakeIntegerSequenceImpl
|
struct TMakeIntegerSequenceImpl
|
||||||
{
|
{
|
||||||
using Type = typename __make_integer_seq<TIntegerSequence, T, N>;
|
using FType = typename __make_integer_seq<TIntegerSequence, T, N>;
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -40,13 +40,13 @@ struct TMakeIntegerSequenceImpl
|
|||||||
template <unsigned N, typename T, T... Ints>
|
template <unsigned N, typename T, T... Ints>
|
||||||
struct TMakeIntegerSequenceImpl
|
struct TMakeIntegerSequenceImpl
|
||||||
{
|
{
|
||||||
using Type = typename TMakeIntegerSequenceImpl<N - 1, T, T(N - 1), Ints...>::Type;
|
using FType = typename TMakeIntegerSequenceImpl<N - 1, T, T(N - 1), Ints...>::FType;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, T... Ints>
|
template <typename T, T... Ints>
|
||||||
struct TMakeIntegerSequenceImpl<0, T, Ints...>
|
struct TMakeIntegerSequenceImpl<0, T, Ints...>
|
||||||
{
|
{
|
||||||
using Type = TIntegerSequence<T, Ints...>;
|
using FType = TIntegerSequence<T, Ints...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -57,7 +57,7 @@ template <size_t... Ints>
|
|||||||
using TIndexSequence = TIntegerSequence<size_t, Ints...>;
|
using TIndexSequence = TIntegerSequence<size_t, Ints...>;
|
||||||
|
|
||||||
template <typename T, T N>
|
template <typename T, T N>
|
||||||
using TMakeIntegerSequence = typename NAMESPACE_PRIVATE::TMakeIntegerSequenceImpl<N, T>::Type;
|
using TMakeIntegerSequence = typename NAMESPACE_PRIVATE::TMakeIntegerSequenceImpl<N, T>::FType;
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
using TMakeIndexSequence = TMakeIntegerSequence<size_t, N>;
|
using TMakeIndexSequence = TMakeIntegerSequence<size_t, N>;
|
||||||
@ -103,7 +103,7 @@ struct TFrontImpl;
|
|||||||
template <typename T, typename... Ts>
|
template <typename T, typename... Ts>
|
||||||
struct TFrontImpl<TTypeSequence<T, Ts...>>
|
struct TFrontImpl<TTypeSequence<T, Ts...>>
|
||||||
{
|
{
|
||||||
using Type = T;
|
using FType = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TSequence>
|
template <typename TSequence>
|
||||||
@ -112,7 +112,7 @@ struct TPopImpl;
|
|||||||
template <typename T, typename... Ts>
|
template <typename T, typename... Ts>
|
||||||
struct TPopImpl<TTypeSequence<T, Ts...>>
|
struct TPopImpl<TTypeSequence<T, Ts...>>
|
||||||
{
|
{
|
||||||
using Type = TTypeSequence<Ts...>;
|
using FType = TTypeSequence<Ts...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename TSequence>
|
template <typename T, typename TSequence>
|
||||||
@ -121,19 +121,19 @@ struct TPushImpl;
|
|||||||
template <typename T, typename... Ts>
|
template <typename T, typename... Ts>
|
||||||
struct TPushImpl<T, TTypeSequence<Ts...>>
|
struct TPushImpl<T, TTypeSequence<Ts...>>
|
||||||
{
|
{
|
||||||
using Type = TTypeSequence<T, Ts...>;
|
using FType = TTypeSequence<T, Ts...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
template <CTTypeSequence TSequence>
|
template <CTTypeSequence TSequence>
|
||||||
using TFront = typename NAMESPACE_PRIVATE::TFrontImpl<TSequence>::Type;
|
using TFront = typename NAMESPACE_PRIVATE::TFrontImpl<TSequence>::FType;
|
||||||
|
|
||||||
template <CTTypeSequence TSequence>
|
template <CTTypeSequence TSequence>
|
||||||
using TPop = typename NAMESPACE_PRIVATE::TPopImpl<TSequence>::Type;
|
using TPop = typename NAMESPACE_PRIVATE::TPopImpl<TSequence>::FType;
|
||||||
|
|
||||||
template <typename T, typename TSequence>
|
template <typename T, typename TSequence>
|
||||||
using TPush = typename NAMESPACE_PRIVATE::TPushImpl<T, TSequence>::Type;
|
using TPush = typename NAMESPACE_PRIVATE::TPushImpl<T, TSequence>::FType;
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_BEGIN
|
NAMESPACE_PRIVATE_BEGIN
|
||||||
|
|
||||||
@ -194,19 +194,19 @@ struct TIndexAssert
|
|||||||
template <size_t I, typename TSequence>
|
template <size_t I, typename TSequence>
|
||||||
struct TTypeImpl
|
struct TTypeImpl
|
||||||
{
|
{
|
||||||
using Type = typename TTypeImpl<I - 1, TPop<TSequence>>::Type;
|
using FType = typename TTypeImpl<I - 1, TPop<TSequence>>::FType;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TSequence>
|
template <typename TSequence>
|
||||||
struct TTypeImpl<0, TSequence>
|
struct TTypeImpl<0, TSequence>
|
||||||
{
|
{
|
||||||
using Type = TFront<TSequence>;
|
using FType = TFront<TSequence>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TSequence>
|
template <typename TSequence>
|
||||||
struct TTypeImpl<INDEX_NONE, TSequence>
|
struct TTypeImpl<INDEX_NONE, TSequence>
|
||||||
{
|
{
|
||||||
using Type = void;
|
using FType = void;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <size_t I, typename TSequence>
|
template <size_t I, typename TSequence>
|
||||||
@ -214,7 +214,7 @@ struct TTypeAssert
|
|||||||
{
|
{
|
||||||
static_assert(I < TSizeImpl<TSequence>::Value, "I is invalid index in type sequence");
|
static_assert(I < TSizeImpl<TSequence>::Value, "I is invalid index in type sequence");
|
||||||
static constexpr size_t SafeIndex = I < TSizeImpl<TSequence>::Value ? I : INDEX_NONE;
|
static constexpr size_t SafeIndex = I < TSizeImpl<TSequence>::Value ? I : INDEX_NONE;
|
||||||
using Type = TCopyCV<TSequence, typename TTypeImpl<SafeIndex, TSequence>::Type>;
|
using FType = TCopyCV<TSequence, typename TTypeImpl<SafeIndex, TSequence>::FType>;
|
||||||
};
|
};
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
@ -226,29 +226,29 @@ template <typename T, CTTypeSequence TSequence>
|
|||||||
inline constexpr size_t TIndex = NAMESPACE_PRIVATE::TIndexAssert<T, TSequence>::Value;
|
inline constexpr size_t TIndex = NAMESPACE_PRIVATE::TIndexAssert<T, TSequence>::Value;
|
||||||
|
|
||||||
template <size_t I, CTTypeSequence TSequence>
|
template <size_t I, CTTypeSequence TSequence>
|
||||||
using TType = typename NAMESPACE_PRIVATE::TTypeAssert<I, TSequence>::Type;
|
using TType = typename NAMESPACE_PRIVATE::TTypeAssert<I, TSequence>::FType;
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_BEGIN
|
NAMESPACE_PRIVATE_BEGIN
|
||||||
|
|
||||||
template <typename TSequence>
|
template <typename TSequence>
|
||||||
struct TUniqueTypeSequenceImpl
|
struct TUniqueTypeSequenceImpl
|
||||||
{
|
{
|
||||||
using FrontType = TFront<TSequence>;
|
using FFrontType = TFront<TSequence>;
|
||||||
using NextSequence = TPop<TSequence>;
|
using FNextSequence = TPop<TSequence>;
|
||||||
using NextUniqueSequence = typename TUniqueTypeSequenceImpl<NextSequence>::Type;
|
using FNextUniqueSequence = typename TUniqueTypeSequenceImpl<FNextSequence>::FType;
|
||||||
using Type = TConditional<!CExistentType<FrontType, NextSequence>, TPush<FrontType, NextUniqueSequence>, NextUniqueSequence>;
|
using FType = TConditional<!CExistentType<FFrontType, FNextSequence>, TPush<FFrontType, FNextUniqueSequence>, FNextUniqueSequence>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct TUniqueTypeSequenceImpl<TTypeSequence<>>
|
struct TUniqueTypeSequenceImpl<TTypeSequence<>>
|
||||||
{
|
{
|
||||||
using Type = TTypeSequence<>;
|
using FType = TTypeSequence<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
template <CTTypeSequence TSequence>
|
template <CTTypeSequence TSequence>
|
||||||
using TUniqueTypeSequence = typename NAMESPACE_PRIVATE::TUniqueTypeSequenceImpl<TSequence>::Type;
|
using TUniqueTypeSequence = typename NAMESPACE_PRIVATE::TUniqueTypeSequenceImpl<TSequence>::FType;
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_BEGIN
|
NAMESPACE_PRIVATE_BEGIN
|
||||||
|
|
||||||
|
@ -45,9 +45,9 @@ class TOptional<T, false> final
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ValueType = T;
|
using FValueType = T;
|
||||||
|
|
||||||
static_assert(!CReference<ValueType>);
|
static_assert(!CReference<FValueType>);
|
||||||
|
|
||||||
/** Constructs an object that does not contain a value. */
|
/** Constructs an object that does not contain a value. */
|
||||||
FORCEINLINE constexpr TOptional() : bIsValid(false) { }
|
FORCEINLINE constexpr TOptional() : bIsValid(false) { }
|
||||||
@ -67,7 +67,7 @@ public:
|
|||||||
FORCEINLINE constexpr explicit TOptional(FInPlace, Ts&&... Args)
|
FORCEINLINE constexpr explicit TOptional(FInPlace, Ts&&... Args)
|
||||||
: bIsValid(true)
|
: bIsValid(true)
|
||||||
{
|
{
|
||||||
new (&Value) ValueType(Forward<Ts>(Args)...);
|
new (&Value) FValueType(Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs an object with initial content an object, direct-non-list-initialized from IL, Forward<Ts>(Args).... */
|
/** Constructs an object with initial content an object, direct-non-list-initialized from IL, Forward<Ts>(Args).... */
|
||||||
@ -75,7 +75,7 @@ public:
|
|||||||
FORCEINLINE constexpr explicit TOptional(FInPlace, initializer_list<W> IL, Ts&&... Args)
|
FORCEINLINE constexpr explicit TOptional(FInPlace, initializer_list<W> IL, Ts&&... Args)
|
||||||
: bIsValid(true)
|
: bIsValid(true)
|
||||||
{
|
{
|
||||||
new (&Value) ValueType(IL, Forward<Ts>(Args)...);
|
new (&Value) FValueType(IL, Forward<Ts>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Copies content of other into a new instance. */
|
/** Copies content of other into a new instance. */
|
||||||
@ -85,7 +85,7 @@ public:
|
|||||||
FORCEINLINE constexpr TOptional(const TOptional& InValue) requires (CCopyConstructible<T> && !CTriviallyCopyConstructible<T>)
|
FORCEINLINE constexpr TOptional(const TOptional& InValue) requires (CCopyConstructible<T> && !CTriviallyCopyConstructible<T>)
|
||||||
: bIsValid(InValue.IsValid())
|
: bIsValid(InValue.IsValid())
|
||||||
{
|
{
|
||||||
if (InValue.IsValid()) new (&Value) ValueType(InValue.GetValue());
|
if (InValue.IsValid()) new (&Value) FValueType(InValue.GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Moves content of other into a new instance. */
|
/** Moves content of other into a new instance. */
|
||||||
@ -95,7 +95,7 @@ public:
|
|||||||
FORCEINLINE constexpr TOptional(TOptional&& InValue) requires (CMoveConstructible<T> && !CTriviallyMoveConstructible<T>)
|
FORCEINLINE constexpr TOptional(TOptional&& InValue) requires (CMoveConstructible<T> && !CTriviallyMoveConstructible<T>)
|
||||||
: bIsValid(InValue.IsValid())
|
: bIsValid(InValue.IsValid())
|
||||||
{
|
{
|
||||||
if (InValue.IsValid()) new (&Value) ValueType(MoveTemp(InValue.GetValue()));
|
if (InValue.IsValid()) new (&Value) FValueType(MoveTemp(InValue.GetValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converting copy constructor. */
|
/** Converting copy constructor. */
|
||||||
@ -103,7 +103,7 @@ public:
|
|||||||
FORCEINLINE constexpr explicit (!CConvertibleTo<const U&, T>) TOptional(const TOptional<U>& InValue)
|
FORCEINLINE constexpr explicit (!CConvertibleTo<const U&, T>) TOptional(const TOptional<U>& InValue)
|
||||||
: bIsValid(InValue.IsValid())
|
: bIsValid(InValue.IsValid())
|
||||||
{
|
{
|
||||||
if (InValue.IsValid()) new (&Value) ValueType(InValue.GetValue());
|
if (InValue.IsValid()) new (&Value) FValueType(InValue.GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converting move constructor. */
|
/** Converting move constructor. */
|
||||||
@ -111,7 +111,7 @@ public:
|
|||||||
FORCEINLINE constexpr explicit (!CConvertibleTo<U&&, T>) TOptional(TOptional<U>&& InValue)
|
FORCEINLINE constexpr explicit (!CConvertibleTo<U&&, T>) TOptional(TOptional<U>&& InValue)
|
||||||
: bIsValid(InValue.IsValid())
|
: bIsValid(InValue.IsValid())
|
||||||
{
|
{
|
||||||
if (InValue.IsValid()) new (&Value) ValueType(MoveTemp(InValue.GetValue()));
|
if (InValue.IsValid()) new (&Value) FValueType(MoveTemp(InValue.GetValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Destroys the contained object, if any, as if by a call to Reset(). */
|
/** Destroys the contained object, if any, as if by a call to Reset(). */
|
||||||
@ -141,7 +141,7 @@ public:
|
|||||||
if (IsValid()) GetValue() = InValue.GetValue();
|
if (IsValid()) GetValue() = InValue.GetValue();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new (&Value) ValueType(InValue.GetValue());
|
new (&Value) FValueType(InValue.GetValue());
|
||||||
bIsValid = true;
|
bIsValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ public:
|
|||||||
if (IsValid()) GetValue() = MoveTemp(InValue.GetValue());
|
if (IsValid()) GetValue() = MoveTemp(InValue.GetValue());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new (&Value) ValueType(MoveTemp(InValue.GetValue()));
|
new (&Value) FValueType(MoveTemp(InValue.GetValue()));
|
||||||
bIsValid = true;
|
bIsValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ public:
|
|||||||
if (IsValid()) GetValue() = InValue.GetValue();
|
if (IsValid()) GetValue() = InValue.GetValue();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new (&Value) ValueType(InValue.GetValue());
|
new (&Value) FValueType(InValue.GetValue());
|
||||||
bIsValid = true;
|
bIsValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ public:
|
|||||||
if (IsValid()) GetValue() = MoveTemp(InValue.GetValue());
|
if (IsValid()) GetValue() = MoveTemp(InValue.GetValue());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new (&Value) ValueType(MoveTemp(InValue.GetValue()));
|
new (&Value) FValueType(MoveTemp(InValue.GetValue()));
|
||||||
bIsValid = true;
|
bIsValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ public:
|
|||||||
if (IsValid()) GetValue() = Forward<U>(InValue);
|
if (IsValid()) GetValue() = Forward<U>(InValue);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new (&Value) ValueType(Forward<U>(InValue));
|
new (&Value) FValueType(Forward<U>(InValue));
|
||||||
bIsValid = true;
|
bIsValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,7 +278,7 @@ public:
|
|||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
|
|
||||||
T* Result = new (&Value) ValueType(Forward<Ts>(Args)...);
|
T* Result = new (&Value) FValueType(Forward<Ts>(Args)...);
|
||||||
bIsValid = true;
|
bIsValid = true;
|
||||||
|
|
||||||
return *Result;
|
return *Result;
|
||||||
@ -298,7 +298,7 @@ public:
|
|||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
|
|
||||||
T* Result = new (&Value) ValueType(IL, Forward<Ts>(Args)...);
|
T* Result = new (&Value) FValueType(IL, Forward<Ts>(Args)...);
|
||||||
bIsValid = true;
|
bIsValid = true;
|
||||||
|
|
||||||
return *Result;
|
return *Result;
|
||||||
@ -335,7 +335,7 @@ public:
|
|||||||
{
|
{
|
||||||
bIsValid = false;
|
bIsValid = false;
|
||||||
|
|
||||||
reinterpret_cast<T*>(&Value)->~ValueType();
|
reinterpret_cast<T*>(&Value)->~FValueType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,9 +380,9 @@ class TOptional<T, true> final
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ValueType = TRemoveReference<T>;
|
using FValueType = TRemoveReference<T>;
|
||||||
|
|
||||||
static_assert(!CReference<ValueType>);
|
static_assert(!CReference<FValueType>);
|
||||||
|
|
||||||
/** Constructs an object that does not contain a reference. */
|
/** Constructs an object that does not contain a reference. */
|
||||||
FORCEINLINE constexpr TOptional() : Ptr(nullptr) { }
|
FORCEINLINE constexpr TOptional() : Ptr(nullptr) { }
|
||||||
@ -408,13 +408,13 @@ public:
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** Converting constructor. */
|
/** Converting constructor. */
|
||||||
template <typename U> requires (!CConst<ValueType> && CConstructibleFrom<T, U&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<U, T>)
|
template <typename U> requires (!CConst<FValueType> && CConstructibleFrom<T, U&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<U, T>)
|
||||||
FORCEINLINE constexpr explicit (!CConvertibleTo<U&, T>) TOptional(TOptional<U, false>& InValue)
|
FORCEINLINE constexpr explicit (!CConvertibleTo<U&, T>) TOptional(TOptional<U, false>& InValue)
|
||||||
: Ptr(InValue.IsValid() ? AddressOf(static_cast<T>(InValue.GetValue())) : nullptr)
|
: Ptr(InValue.IsValid() ? AddressOf(static_cast<T>(InValue.GetValue())) : nullptr)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** Converting constructor. */
|
/** Converting constructor. */
|
||||||
template <typename U> requires (CConst<ValueType> && CConstructibleFrom<T, const U&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<U, T>)
|
template <typename U> requires (CConst<FValueType> && CConstructibleFrom<T, const U&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<U, T>)
|
||||||
FORCEINLINE constexpr explicit (!CConvertibleTo<const U&, T>) TOptional(const TOptional<U, false>& InValue)
|
FORCEINLINE constexpr explicit (!CConvertibleTo<const U&, T>) TOptional(const TOptional<U, false>& InValue)
|
||||||
: Ptr(InValue.IsValid() ? AddressOf(static_cast<T>(InValue.GetValue())) : nullptr)
|
: Ptr(InValue.IsValid() ? AddressOf(static_cast<T>(InValue.GetValue())) : nullptr)
|
||||||
{ }
|
{ }
|
||||||
@ -492,7 +492,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ValueType* Ptr;
|
FValueType* Ptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class TPropagateConst final
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using ElementType = TPointerTraits<T>::ElementType;
|
using FElementType = TPointerTraits<T>::FElementType;
|
||||||
|
|
||||||
/** Constructs an TPropagateConst, default-initializing underlying pointer. */
|
/** Constructs an TPropagateConst, default-initializing underlying pointer. */
|
||||||
FORCEINLINE constexpr TPropagateConst() = default;
|
FORCEINLINE constexpr TPropagateConst() = default;
|
||||||
@ -105,26 +105,26 @@ public:
|
|||||||
NODISCARD FORCEINLINE constexpr decltype(auto) operator<=>(U InPtr) const& { return SynthThreeWayCompare(Ptr, InPtr); }
|
NODISCARD FORCEINLINE constexpr decltype(auto) operator<=>(U InPtr) const& { return SynthThreeWayCompare(Ptr, InPtr); }
|
||||||
|
|
||||||
/** @return The pointer to the object pointed to by the wrapped pointer. */
|
/** @return The pointer to the object pointed to by the wrapped pointer. */
|
||||||
NODISCARD FORCEINLINE constexpr ElementType* Get() { return TPointerTraits<T>::ToAddress(Ptr); }
|
NODISCARD FORCEINLINE constexpr FElementType* Get() { return TPointerTraits<T>::ToAddress(Ptr); }
|
||||||
NODISCARD FORCEINLINE constexpr const ElementType* Get() const { return TPointerTraits<T>::ToAddress(Ptr); }
|
NODISCARD FORCEINLINE constexpr const FElementType* Get() const { return TPointerTraits<T>::ToAddress(Ptr); }
|
||||||
|
|
||||||
/** @return true if *this owns an object, false otherwise. */
|
/** @return true if *this owns an object, false otherwise. */
|
||||||
NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; }
|
NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; }
|
||||||
NODISCARD FORCEINLINE constexpr explicit operator bool() const { return Get() != nullptr; }
|
NODISCARD FORCEINLINE constexpr explicit operator bool() const { return Get() != nullptr; }
|
||||||
|
|
||||||
/** @return The a reference or pointer to the object owned by *this, i.e. Get(). */
|
/** @return The a reference or pointer to the object owned by *this, i.e. Get(). */
|
||||||
NODISCARD FORCEINLINE constexpr ElementType& operator*() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); }
|
NODISCARD FORCEINLINE constexpr FElementType& operator*() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); }
|
||||||
NODISCARD FORCEINLINE constexpr const ElementType& operator*() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); }
|
NODISCARD FORCEINLINE constexpr const FElementType& operator*() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); }
|
||||||
NODISCARD FORCEINLINE constexpr ElementType* operator->() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); }
|
NODISCARD FORCEINLINE constexpr FElementType* operator->() { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); }
|
||||||
NODISCARD FORCEINLINE constexpr const ElementType* operator->() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); }
|
NODISCARD FORCEINLINE constexpr const FElementType* operator->() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); }
|
||||||
|
|
||||||
/** @return The element at index, i.e. Get()[Index]. */
|
/** @return The element at index, i.e. Get()[Index]. */
|
||||||
NODISCARD FORCEINLINE constexpr T& operator[](size_t Index) { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get()[Index]; }
|
NODISCARD FORCEINLINE constexpr T& operator[](size_t Index) { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get()[Index]; }
|
||||||
NODISCARD FORCEINLINE constexpr const T& operator[](size_t Index) const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get()[Index]; }
|
NODISCARD FORCEINLINE constexpr const T& operator[](size_t Index) const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get()[Index]; }
|
||||||
|
|
||||||
/** @return The pointer to the object pointed to by the wrapped pointer-like object. */
|
/** @return The pointer to the object pointed to by the wrapped pointer-like object. */
|
||||||
NODISCARD FORCEINLINE constexpr operator ElementType*() requires (CConvertibleTo<T, ElementType*>) { return Ptr; }
|
NODISCARD FORCEINLINE constexpr operator FElementType*() requires (CConvertibleTo<T, FElementType*>) { return Ptr; }
|
||||||
NODISCARD FORCEINLINE constexpr operator const ElementType*() const requires (CConvertibleTo<T, ElementType*>) { return Ptr; }
|
NODISCARD FORCEINLINE constexpr operator const FElementType*() const requires (CConvertibleTo<T, FElementType*>) { return Ptr; }
|
||||||
|
|
||||||
/** @return The reference to the pointer-like object stored. */
|
/** @return The reference to the pointer-like object stored. */
|
||||||
NODISCARD FORCEINLINE constexpr T& GetUnderlying() { return Ptr; }
|
NODISCARD FORCEINLINE constexpr T& GetUnderlying() { return Ptr; }
|
||||||
|
@ -22,7 +22,7 @@ class TReferenceWrapper final
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using Type = ReferencedType;
|
using FType = ReferencedType;
|
||||||
|
|
||||||
/** Constructs a new reference wrapper. */
|
/** Constructs a new reference wrapper. */
|
||||||
template <typename T = ReferencedType&> requires (CConvertibleTo<T&&, ReferencedType&> && !CSameAs<TReferenceWrapper, TRemoveCVRef<T>>)
|
template <typename T = ReferencedType&> requires (CConvertibleTo<T&&, ReferencedType&> && !CSameAs<TReferenceWrapper, TRemoveCVRef<T>>)
|
||||||
@ -111,10 +111,10 @@ NAMESPACE_PRIVATE_BEGIN
|
|||||||
template <typename T> struct TIsTReferenceWrapperImpl : FFalse { };
|
template <typename T> struct TIsTReferenceWrapperImpl : FFalse { };
|
||||||
template <typename T> struct TIsTReferenceWrapperImpl<TReferenceWrapper<T>> : FTrue { };
|
template <typename T> struct TIsTReferenceWrapperImpl<TReferenceWrapper<T>> : FTrue { };
|
||||||
|
|
||||||
template <typename T> struct TUnwrapReferenceImpl { using Type = T; };
|
template <typename T> struct TUnwrapReferenceImpl { using FType = T; };
|
||||||
template <typename T> struct TUnwrapReferenceImpl<TReferenceWrapper<T>> { using Type = T&; };
|
template <typename T> struct TUnwrapReferenceImpl<TReferenceWrapper<T>> { using FType = T&; };
|
||||||
|
|
||||||
template <typename T> struct TUnwrapRefDecayImpl { using Type = typename TUnwrapReferenceImpl<TDecay<T>>::Type; };
|
template <typename T> struct TUnwrapRefDecayImpl { using FType = typename TUnwrapReferenceImpl<TDecay<T>>::FType; };
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
@ -122,10 +122,10 @@ template <typename T>
|
|||||||
concept CTReferenceWrapper = NAMESPACE_PRIVATE::TIsTReferenceWrapperImpl<TRemoveCV<T>>::Value;
|
concept CTReferenceWrapper = NAMESPACE_PRIVATE::TIsTReferenceWrapperImpl<TRemoveCV<T>>::Value;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using TUnwrapReference = typename NAMESPACE_PRIVATE::TUnwrapReferenceImpl<T>::Type;
|
using TUnwrapReference = typename NAMESPACE_PRIVATE::TUnwrapReferenceImpl<T>::FType;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using TUnwrapRefDecay = typename NAMESPACE_PRIVATE::TUnwrapRefDecayImpl<T>::Type;
|
using TUnwrapRefDecay = typename NAMESPACE_PRIVATE::TUnwrapRefDecayImpl<T>::FType;
|
||||||
|
|
||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
NAMESPACE_MODULE_END(Redcraft)
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
|
@ -49,7 +49,7 @@ struct TTupleElementImpl;
|
|||||||
template <size_t I, typename... Ts>
|
template <size_t I, typename... Ts>
|
||||||
struct TTupleElementImpl<I, TTuple<Ts...>>
|
struct TTupleElementImpl<I, TTuple<Ts...>>
|
||||||
{
|
{
|
||||||
using Type = Meta::TType<I, TTypeSequence<Ts...>>;
|
using FType = Meta::TType<I, TTypeSequence<Ts...>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <bool bTrue, typename... Ts>
|
template <bool bTrue, typename... Ts>
|
||||||
@ -77,12 +77,12 @@ struct TTupleBasicElement
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using ValueType = T;
|
using FValueType = T;
|
||||||
ValueType Value;
|
FValueType Value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type> requires (CConstructibleFrom<T, Type&&>)
|
||||||
FORCEINLINE constexpr TTupleBasicElement(Type&& Arg)
|
FORCEINLINE constexpr TTupleBasicElement(Type&& Arg)
|
||||||
: Value(Forward<Type>(Arg))
|
: Value(Forward<Type>(Arg))
|
||||||
{ }
|
{ }
|
||||||
@ -110,10 +110,10 @@ public:
|
|||||||
template <typename T> \
|
template <typename T> \
|
||||||
struct TTupleBasicElement<T, Index> \
|
struct TTupleBasicElement<T, Index> \
|
||||||
{ \
|
{ \
|
||||||
using Name##Type = T; \
|
using F##Name##Type = T; \
|
||||||
Name##Type Name; \
|
F##Name##Type Name; \
|
||||||
\
|
\
|
||||||
template <typename Type> \
|
template <typename Type> requires (CConstructibleFrom<T, F##Name##Type&&>) \
|
||||||
FORCEINLINE constexpr TTupleBasicElement(Type&& Arg) \
|
FORCEINLINE constexpr TTupleBasicElement(Type&& Arg) \
|
||||||
: Name(Forward<Type>(Arg)) \
|
: Name(Forward<Type>(Arg)) \
|
||||||
{ } \
|
{ } \
|
||||||
@ -315,15 +315,15 @@ template <typename T, CTTuple U>
|
|||||||
inline constexpr size_t TTupleIndex = NAMESPACE_PRIVATE::TTupleIndexImpl<T, TRemoveCV<U>>::Value;
|
inline constexpr size_t TTupleIndex = NAMESPACE_PRIVATE::TTupleIndexImpl<T, TRemoveCV<U>>::Value;
|
||||||
|
|
||||||
template <size_t I, CTTuple U>
|
template <size_t I, CTTuple U>
|
||||||
using TTupleElement = TCopyCV<U, typename NAMESPACE_PRIVATE::TTupleElementImpl<I, TRemoveCV<U>>::Type>;
|
using TTupleElement = TCopyCV<U, typename NAMESPACE_PRIVATE::TTupleElementImpl<I, TRemoveCV<U>>::FType>;
|
||||||
|
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
class TTuple final : public NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>
|
class TTuple final : public NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Super = NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>;
|
using FSuper = NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Ts...>, Ts...>;
|
||||||
using Helper = NAMESPACE_PRIVATE::TTupleHelper<TIndexSequenceFor<Ts...>>;
|
using FHelper = NAMESPACE_PRIVATE::TTupleHelper<TIndexSequenceFor<Ts...>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -334,7 +334,7 @@ public:
|
|||||||
template <typename... Us> requires (sizeof...(Ts) >= 1 && sizeof...(Us) == sizeof...(Ts))
|
template <typename... Us> requires (sizeof...(Ts) >= 1 && sizeof...(Us) == sizeof...(Ts))
|
||||||
&& (true && ... && CConstructibleFrom<Ts, Us&&>)
|
&& (true && ... && CConstructibleFrom<Ts, Us&&>)
|
||||||
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(Us&&... Args)
|
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(Us&&... Args)
|
||||||
: Super(NAMESPACE_PRIVATE::ForwardingConstructor, Forward<Us>(Args)...)
|
: FSuper(NAMESPACE_PRIVATE::ForwardingConstructor, Forward<Us>(Args)...)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** Converting copy constructor. Initializes each element of the tuple with the corresponding element of other. */
|
/** Converting copy constructor. Initializes each element of the tuple with the corresponding element of other. */
|
||||||
@ -342,7 +342,7 @@ public:
|
|||||||
&& (true && ... && CConstructibleFrom<Ts, const Us&>)
|
&& (true && ... && CConstructibleFrom<Ts, const Us&>)
|
||||||
&& NAMESPACE_PRIVATE::TTupleConvertCopy<sizeof...(Ts) != 1, Ts..., Us...>::Value)
|
&& NAMESPACE_PRIVATE::TTupleConvertCopy<sizeof...(Ts) != 1, Ts..., Us...>::Value)
|
||||||
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(const TTuple<Us...>& InValue)
|
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(const TTuple<Us...>& InValue)
|
||||||
: Super(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue)
|
: FSuper(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** Converting move constructor. Initializes each element of the tuple with the corresponding element of other. */
|
/** Converting move constructor. Initializes each element of the tuple with the corresponding element of other. */
|
||||||
@ -350,7 +350,7 @@ public:
|
|||||||
&& (true && ... && CConstructibleFrom<Ts, Us&&>)
|
&& (true && ... && CConstructibleFrom<Ts, Us&&>)
|
||||||
&& NAMESPACE_PRIVATE::TTupleConvertMove<sizeof...(Ts) != 1, Ts..., Us...>::Value)
|
&& NAMESPACE_PRIVATE::TTupleConvertMove<sizeof...(Ts) != 1, Ts..., Us...>::Value)
|
||||||
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(TTuple<Us...>&& InValue)
|
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(TTuple<Us...>&& InValue)
|
||||||
: Super(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue))
|
: FSuper(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** Copies/moves content of other into a new instance. */
|
/** Copies/moves content of other into a new instance. */
|
||||||
@ -362,7 +362,7 @@ public:
|
|||||||
&& (true && ... && CAssignableFrom<Ts&, const Us&>))
|
&& (true && ... && CAssignableFrom<Ts&, const Us&>))
|
||||||
FORCEINLINE constexpr TTuple& operator=(const TTuple<Us...>& InValue)
|
FORCEINLINE constexpr TTuple& operator=(const TTuple<Us...>& InValue)
|
||||||
{
|
{
|
||||||
Helper::Assign(*this, InValue);
|
FHelper::Assign(*this, InValue);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +371,7 @@ public:
|
|||||||
&& (true && ... && CAssignableFrom<Ts&, Us&&>))
|
&& (true && ... && CAssignableFrom<Ts&, Us&&>))
|
||||||
FORCEINLINE constexpr TTuple& operator=(TTuple<Us...>&& InValue)
|
FORCEINLINE constexpr TTuple& operator=(TTuple<Us...>&& InValue)
|
||||||
{
|
{
|
||||||
Helper::Assign(*this, MoveTemp(InValue));
|
FHelper::Assign(*this, MoveTemp(InValue));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,8 +396,8 @@ public:
|
|||||||
template <typename... Us> requires (sizeof...(Ts) == sizeof...(Us) && NAMESPACE_PRIVATE::CTTupleSynthThreeWayComparable<TTypeSequence<Ts...>, TTypeSequence<Us...>>)
|
template <typename... Us> requires (sizeof...(Ts) == sizeof...(Us) && NAMESPACE_PRIVATE::CTTupleSynthThreeWayComparable<TTypeSequence<Ts...>, TTypeSequence<Us...>>)
|
||||||
NODISCARD friend FORCEINLINE constexpr TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...> operator<=>(const TTuple& LHS, const TTuple<Us...>& RHS)
|
NODISCARD friend FORCEINLINE constexpr TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...> operator<=>(const TTuple& LHS, const TTuple<Us...>& RHS)
|
||||||
{
|
{
|
||||||
using R = TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...>;
|
using FResult = TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...>;
|
||||||
return NAMESPACE_PRIVATE::TTupleThreeWay<R, TMakeIndexSequence<sizeof...(Ts)>>::Do(LHS, RHS);
|
return NAMESPACE_PRIVATE::TTupleThreeWay<FResult, TMakeIndexSequence<sizeof...(Ts)>>::Do(LHS, RHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Extracts the Ith element from the tuple. I must be an integer value in [0, sizeof...(Ts)). */
|
/** Extracts the Ith element from the tuple. I must be an integer value in [0, sizeof...(Ts)). */
|
||||||
@ -421,14 +421,14 @@ public:
|
|||||||
template <typename T> NODISCARD FORCEINLINE constexpr decltype(auto) GetValue() const volatile&& { return static_cast<const volatile TTuple&&>(*this).GetValue<TTupleIndex<T, TTuple>>(); }
|
template <typename T> NODISCARD FORCEINLINE constexpr decltype(auto) GetValue() const volatile&& { return static_cast<const volatile TTuple&&>(*this).GetValue<TTupleIndex<T, TTuple>>(); }
|
||||||
|
|
||||||
/** Invoke the callable object 'Func' with a tuple of arguments. */
|
/** Invoke the callable object 'Func' with a tuple of arguments. */
|
||||||
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) & { return Helper::Apply(Forward<F>(Func), static_cast< TTuple& >(*this)); }
|
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) & { return FHelper::Apply(Forward<F>(Func), static_cast< TTuple& >(*this)); }
|
||||||
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const & { return Helper::Apply(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
|
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const & { return FHelper::Apply(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
|
||||||
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile& { return Helper::Apply(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
|
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile& { return FHelper::Apply(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
|
||||||
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile& { return Helper::Apply(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
|
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile& { return FHelper::Apply(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
|
||||||
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) && { return Helper::Apply(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
|
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) && { return FHelper::Apply(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
|
||||||
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const && { return Helper::Apply(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
|
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const && { return FHelper::Apply(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
|
||||||
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile&& { return Helper::Apply(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
|
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile&& { return FHelper::Apply(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
|
||||||
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile&& { return Helper::Apply(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this)); }
|
template <typename F> requires (CInvocable<F, Ts...>) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile&& { return FHelper::Apply(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this)); }
|
||||||
|
|
||||||
/** Visits each element in a tuple in parallel and applies it as arguments to the function. */
|
/** Visits each element in a tuple in parallel and applies it as arguments to the function. */
|
||||||
template <typename F> requires (true && ... && CInvocable<F, Ts>) FORCEINLINE constexpr void Visit(F&& Func) & { VisitTuple(Forward<F>(Func), static_cast< TTuple& >(*this)); }
|
template <typename F> requires (true && ... && CInvocable<F, Ts>) FORCEINLINE constexpr void Visit(F&& Func) & { VisitTuple(Forward<F>(Func), static_cast< TTuple& >(*this)); }
|
||||||
@ -461,24 +461,24 @@ public:
|
|||||||
template <typename Ret, typename F> requires ((sizeof...(Ts) >= 1) && ... && CInvocableResult<Ret, F, Ts>) FORCEINLINE constexpr Ret Visit(F&& Func, size_t Index) const volatile&& { return NAMESPACE_PRIVATE::TTupleVisitElementByIndex<Ret, TMakeIndexSequence<sizeof...(Ts)>>::Do(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this), Index); }
|
template <typename Ret, typename F> requires ((sizeof...(Ts) >= 1) && ... && CInvocableResult<Ret, F, Ts>) FORCEINLINE constexpr Ret Visit(F&& Func, size_t Index) const volatile&& { return NAMESPACE_PRIVATE::TTupleVisitElementByIndex<Ret, TMakeIndexSequence<sizeof...(Ts)>>::Do(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this), Index); }
|
||||||
|
|
||||||
/** Transform a tuple into another tuple using the given function. */
|
/** Transform a tuple into another tuple using the given function. */
|
||||||
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) & { return Helper::Transform(Forward<F>(Func), static_cast< TTuple& >(*this)); }
|
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) & { return FHelper::Transform(Forward<F>(Func), static_cast< TTuple& >(*this)); }
|
||||||
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const & { return Helper::Transform(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
|
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const & { return FHelper::Transform(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
|
||||||
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile& { return Helper::Transform(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
|
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile& { return FHelper::Transform(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
|
||||||
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile& { return Helper::Transform(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
|
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile& { return FHelper::Transform(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
|
||||||
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) && { return Helper::Transform(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
|
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) && { return FHelper::Transform(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
|
||||||
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const && { return Helper::Transform(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
|
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const && { return FHelper::Transform(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
|
||||||
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile&& { return Helper::Transform(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
|
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile&& { return FHelper::Transform(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
|
||||||
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile&& { return Helper::Transform(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this)); }
|
template <typename F> requires (true && ... && (CInvocable<F, Ts> && !CSameAs<void, TInvokeResult<F, Ts>>)) NODISCARD FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile&& { return FHelper::Transform(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this)); }
|
||||||
|
|
||||||
/** Constructs an object of type T with a tuple as an argument. */
|
/** Constructs an object of type T with a tuple as an argument. */
|
||||||
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() & { return Helper::template Construct<T>(static_cast< TTuple& >(*this)); }
|
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() & { return FHelper::template Construct<T>(static_cast< TTuple& >(*this)); }
|
||||||
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const & { return Helper::template Construct<T>(static_cast<const TTuple& >(*this)); }
|
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const & { return FHelper::template Construct<T>(static_cast<const TTuple& >(*this)); }
|
||||||
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile& { return Helper::template Construct<T>(static_cast< volatile TTuple& >(*this)); }
|
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile& { return FHelper::template Construct<T>(static_cast< volatile TTuple& >(*this)); }
|
||||||
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const volatile& { return Helper::template Construct<T>(static_cast<const volatile TTuple& >(*this)); }
|
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const volatile& { return FHelper::template Construct<T>(static_cast<const volatile TTuple& >(*this)); }
|
||||||
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() && { return Helper::template Construct<T>(static_cast< TTuple&&>(*this)); }
|
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() && { return FHelper::template Construct<T>(static_cast< TTuple&&>(*this)); }
|
||||||
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const && { return Helper::template Construct<T>(static_cast<const TTuple&&>(*this)); }
|
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const && { return FHelper::template Construct<T>(static_cast<const TTuple&&>(*this)); }
|
||||||
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile&& { return Helper::template Construct<T>(static_cast< volatile TTuple&&>(*this)); }
|
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() volatile&& { return FHelper::template Construct<T>(static_cast< volatile TTuple&&>(*this)); }
|
||||||
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const volatile&& { return Helper::template Construct<T>(static_cast<const volatile TTuple&&>(*this)); }
|
template <typename T> requires (CConstructibleFrom<T, Ts...>) NODISCARD FORCEINLINE constexpr T Construct() const volatile&& { return FHelper::template Construct<T>(static_cast<const volatile TTuple&&>(*this)); }
|
||||||
|
|
||||||
/** @return The number of elements in the tuple. */
|
/** @return The number of elements in the tuple. */
|
||||||
NODISCARD static FORCEINLINE constexpr size_t Num() { return sizeof...(Ts); }
|
NODISCARD static FORCEINLINE constexpr size_t Num() { return sizeof...(Ts); }
|
||||||
@ -555,13 +555,13 @@ struct TTupleCatResultImpl;
|
|||||||
template <typename... Ts, typename... TTupleTypes>
|
template <typename... Ts, typename... TTupleTypes>
|
||||||
struct TTupleCatResultImpl<TTuple<Ts...>, TTupleTypes...>
|
struct TTupleCatResultImpl<TTuple<Ts...>, TTupleTypes...>
|
||||||
{
|
{
|
||||||
using Type = typename TTupleCatResultImpl<TTupleTypes..., Ts...>::Type;
|
using FType = typename TTupleCatResultImpl<TTupleTypes..., Ts...>::FType;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
struct TTupleCatResultImpl<FTupleEndFlag, Ts...>
|
struct TTupleCatResultImpl<FTupleEndFlag, Ts...>
|
||||||
{
|
{
|
||||||
using Type = TTuple<Ts...>;
|
using FType = TTuple<Ts...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename R, typename Indices>
|
template <typename R, typename Indices>
|
||||||
@ -571,14 +571,14 @@ template <typename... RTypes, size_t... Indices>
|
|||||||
struct TTupleCatMake<TTuple<RTypes...>, TIndexSequence<Indices...>>
|
struct TTupleCatMake<TTuple<RTypes...>, TIndexSequence<Indices...>>
|
||||||
{
|
{
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
struct ForwardType { using Type = TConditional<CRValueReference<T>, TRemoveReference<U>&&, U>; };
|
struct FForwardType { using FType = TConditional<CRValueReference<T>, TRemoveReference<U>&&, U>; };
|
||||||
|
|
||||||
template <typename TTupleType>
|
template <typename TTupleType>
|
||||||
FORCEINLINE static constexpr TTuple<RTypes...> Do(TTupleType&& InValue)
|
FORCEINLINE static constexpr TTuple<RTypes...> Do(TTupleType&& InValue)
|
||||||
{
|
{
|
||||||
return TTuple<RTypes...>
|
return TTuple<RTypes...>
|
||||||
(
|
(
|
||||||
static_cast<typename ForwardType<RTypes, decltype(Forward<TTupleType>(InValue).template GetValue<Indices>())>::Type>
|
static_cast<typename FForwardType<RTypes, decltype(Forward<TTupleType>(InValue).template GetValue<Indices>())>::FType>
|
||||||
(
|
(
|
||||||
Forward<TTupleType>(InValue).template GetValue<Indices>()
|
Forward<TTupleType>(InValue).template GetValue<Indices>()
|
||||||
)...
|
)...
|
||||||
@ -642,15 +642,15 @@ struct TTupleVisitImpl<TIndexSequence<>>
|
|||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
template <typename... TTupleTypes> requires (true && ... && CTTuple<TRemoveCVRef<TTupleTypes>>)
|
template <typename... TTupleTypes> requires (true && ... && CTTuple<TRemoveCVRef<TTupleTypes>>)
|
||||||
using TTupleCatResult = typename NAMESPACE_PRIVATE::TTupleCatResultImpl<TRemoveReference<TTupleTypes>..., NAMESPACE_PRIVATE::FTupleEndFlag>::Type;;
|
using TTupleCatResult = typename NAMESPACE_PRIVATE::TTupleCatResultImpl<TRemoveReference<TTupleTypes>..., NAMESPACE_PRIVATE::FTupleEndFlag>::FType;
|
||||||
|
|
||||||
/** Creates a tuple by concatenating any number of tuples. */
|
/** Creates a tuple by concatenating any number of tuples. */
|
||||||
template <typename... TTupleTypes> requires (true && ... && CTTuple<TRemoveCVRef<TTupleTypes>>)
|
template <typename... TTupleTypes> requires (true && ... && CTTuple<TRemoveCVRef<TTupleTypes>>)
|
||||||
FORCEINLINE constexpr decltype(auto) TupleCat(TTupleTypes&&... Args)
|
FORCEINLINE constexpr decltype(auto) TupleCat(TTupleTypes&&... Args)
|
||||||
{
|
{
|
||||||
using R = TTupleCatResult<TTupleTypes...>;
|
using FResult = TTupleCatResult<TTupleTypes...>;
|
||||||
if constexpr (sizeof...(Args) == 0) return R();
|
if constexpr (sizeof...(Args) == 0) return FResult();
|
||||||
else return NAMESPACE_PRIVATE::TTupleCatImpl<R>::Do(Forward<TTupleTypes>(Args)...);
|
else return NAMESPACE_PRIVATE::TTupleCatImpl<FResult>::Do(Forward<TTupleTypes>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -679,20 +679,22 @@ FORCEINLINE constexpr void VisitTuple(F&& Func, FirstTupleType&& FirstTuple, Tup
|
|||||||
template <typename... Ts, typename... Us> requires (requires { typename TTuple<TCommonType<Ts, Us>...>; })
|
template <typename... Ts, typename... Us> requires (requires { typename TTuple<TCommonType<Ts, Us>...>; })
|
||||||
struct TBasicCommonType<TTuple<Ts...>, TTuple<Us...>>
|
struct TBasicCommonType<TTuple<Ts...>, TTuple<Us...>>
|
||||||
{
|
{
|
||||||
using Type = TTuple<TCommonType<Ts, Us>...>;
|
using FType = TTuple<TCommonType<Ts, Us>...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Ts, typename... Us, template<typename> typename TQualifiers, template<typename> typename UQualifiers>
|
template <typename... Ts, typename... Us, template<typename> typename TQualifiers, template<typename> typename UQualifiers>
|
||||||
requires (requires { typename TTuple<TCommonReference<TQualifiers<Ts>, UQualifiers<Us>>...>; })
|
requires (requires { typename TTuple<TCommonReference<TQualifiers<Ts>, UQualifiers<Us>>...>; })
|
||||||
struct TBasicCommonReference<TTuple<Ts...>, TTuple<Us...>, TQualifiers, UQualifiers>
|
struct TBasicCommonReference<TTuple<Ts...>, TTuple<Us...>, TQualifiers, UQualifiers>
|
||||||
{
|
{
|
||||||
using Type = TTuple<TCommonReference<TQualifiers<Ts>, UQualifiers<Us>>...>;
|
using FType = TTuple<TCommonReference<TQualifiers<Ts>, UQualifiers<Us>>...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
NAMESPACE_MODULE_END(Redcraft)
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
NAMESPACE_REDCRAFT_END
|
NAMESPACE_REDCRAFT_END
|
||||||
|
|
||||||
|
// ReSharper disable CppInconsistentNaming
|
||||||
|
|
||||||
NAMESPACE_STD_BEGIN
|
NAMESPACE_STD_BEGIN
|
||||||
|
|
||||||
// Support structure binding, should not be directly used.
|
// Support structure binding, should not be directly used.
|
||||||
@ -718,3 +720,5 @@ template <size_t Index, typename ...Ts> FORCEINLINE constexpr decltype(auto) get
|
|||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
NAMESPACE_MODULE_END(Redcraft)
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
NAMESPACE_REDCRAFT_END
|
NAMESPACE_REDCRAFT_END
|
||||||
|
|
||||||
|
// ReSharper restore CppInconsistentNaming
|
||||||
|
@ -24,8 +24,8 @@ void AsConst(const T&& Ref) = delete;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
FORCEINLINE constexpr TRemoveReference<T>&& MoveTemp(T&& Obj)
|
FORCEINLINE constexpr TRemoveReference<T>&& MoveTemp(T&& Obj)
|
||||||
{
|
{
|
||||||
using CastType = TRemoveReference<T>;
|
using FCastType = TRemoveReference<T>;
|
||||||
return static_cast<CastType&&>(Obj);
|
return static_cast<FCastType&&>(Obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** CopyTemp will enforce the creation of an rvalue which can bind to rvalue reference parameters. */
|
/** CopyTemp will enforce the creation of an rvalue which can bind to rvalue reference parameters. */
|
||||||
|
@ -40,30 +40,30 @@ struct TVariantAlternativeImpl;
|
|||||||
template <size_t I, typename... Ts>
|
template <size_t I, typename... Ts>
|
||||||
struct TVariantAlternativeImpl<I, TVariant<Ts...>>
|
struct TVariantAlternativeImpl<I, TVariant<Ts...>>
|
||||||
{
|
{
|
||||||
using Type = Meta::TType<I, TTypeSequence<Ts...>>;
|
using FType = Meta::TType<I, TTypeSequence<Ts...>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename TSequence>
|
template <typename T, typename TSequence>
|
||||||
struct TVariantOverloadType
|
struct TVariantOverloadType
|
||||||
{
|
{
|
||||||
using FrontType = Meta::TFront<TSequence>;
|
using FFrontType = Meta::TFront<TSequence>;
|
||||||
using NextSequence = Meta::TPop<TSequence>;
|
using FNextSequence = Meta::TPop<TSequence>;
|
||||||
using NextUniqueSequence = typename TVariantOverloadType<T, NextSequence>::Type;
|
using FNextUniqueSequence = typename TVariantOverloadType<T, FNextSequence>::FType;
|
||||||
|
|
||||||
// T_i x[] = { Forward<T>(t) };
|
// T_i x[] = { Forward<T>(t) };
|
||||||
static constexpr bool bConditional = requires { DeclVal<void(FrontType(&&)[1])>()({ DeclVal<T>() }); };
|
static constexpr bool bConditional = requires { DeclVal<void(FFrontType(&&)[1])>()({ DeclVal<T>() }); };
|
||||||
|
|
||||||
using Type = TConditional<bConditional, Meta::TPush<FrontType, NextUniqueSequence>, NextUniqueSequence>;
|
using FType = TConditional<bConditional, Meta::TPush<FFrontType, FNextUniqueSequence>, FNextUniqueSequence>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct TVariantOverloadType<T, TTypeSequence<>>
|
struct TVariantOverloadType<T, TTypeSequence<>>
|
||||||
{
|
{
|
||||||
using Type = TTypeSequence<>;
|
using FType = TTypeSequence<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename... Ts>
|
template <typename T, typename... Ts>
|
||||||
using TVariantSelectedType = Meta::TOverloadResolution<T, typename NAMESPACE_PRIVATE::TVariantOverloadType<T, TTypeSequence<Ts...>>::Type>;
|
using TVariantSelectedType = Meta::TOverloadResolution<T, typename NAMESPACE_PRIVATE::TVariantOverloadType<T, TTypeSequence<Ts...>>::FType>;
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ template <typename T, CTVariant U>
|
|||||||
inline constexpr size_t TVariantIndex = NAMESPACE_PRIVATE::TVariantIndexImpl<T, TRemoveCV<U>>::Value;
|
inline constexpr size_t TVariantIndex = NAMESPACE_PRIVATE::TVariantIndexImpl<T, TRemoveCV<U>>::Value;
|
||||||
|
|
||||||
template <size_t I, CTVariant U>
|
template <size_t I, CTVariant U>
|
||||||
using TVariantAlternative = TCopyCV<U, typename NAMESPACE_PRIVATE::TVariantAlternativeImpl<I, TRemoveCV<U>>::Type>;
|
using TVariantAlternative = TCopyCV<U, typename NAMESPACE_PRIVATE::TVariantAlternativeImpl<I, TRemoveCV<U>>::FType>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class template TVariant represents a type-safe union. An instance of TVariant
|
* The class template TVariant represents a type-safe union. An instance of TVariant
|
||||||
@ -139,8 +139,8 @@ public:
|
|||||||
FORCEINLINE constexpr explicit TVariant(TInPlaceIndex<I>, Us&&... Args)
|
FORCEINLINE constexpr explicit TVariant(TInPlaceIndex<I>, Us&&... Args)
|
||||||
: TypeIndex(I)
|
: TypeIndex(I)
|
||||||
{
|
{
|
||||||
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
|
using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
|
||||||
new (&Value) SelectedType(Forward<Us>(Args)...);
|
new (&Value) FSelectedType(Forward<Us>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs a variant with the specified alternative T and initializes the contained value with the arguments IL, Forward<Us>(Args).... */
|
/** Constructs a variant with the specified alternative T and initializes the contained value with the arguments IL, Forward<Us>(Args).... */
|
||||||
@ -155,8 +155,8 @@ public:
|
|||||||
FORCEINLINE constexpr explicit TVariant(TInPlaceIndex<I>, initializer_list<T> IL, Us&&... Args)
|
FORCEINLINE constexpr explicit TVariant(TInPlaceIndex<I>, initializer_list<T> IL, Us&&... Args)
|
||||||
: TypeIndex(I)
|
: TypeIndex(I)
|
||||||
{
|
{
|
||||||
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
|
using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
|
||||||
new (&Value) SelectedType(IL, Forward<Us>(Args)...);
|
new (&Value) FSelectedType(IL, Forward<Us>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Destroys the contained object, if any, as if by a call to Reset(). */
|
/** Destroys the contained object, if any, as if by a call to Reset(). */
|
||||||
@ -224,14 +224,14 @@ public:
|
|||||||
template <typename T> requires (requires { typename NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>; })
|
template <typename T> requires (requires { typename NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>; })
|
||||||
FORCEINLINE constexpr TVariant& operator=(T&& InValue)
|
FORCEINLINE constexpr TVariant& operator=(T&& InValue)
|
||||||
{
|
{
|
||||||
using SelectedType = NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>;
|
using FSelectedType = NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>;
|
||||||
|
|
||||||
if (GetIndex() == TVariantIndex<SelectedType, TVariant<Ts...>>) GetValue<SelectedType>() = Forward<T>(InValue);
|
if (GetIndex() == TVariantIndex<FSelectedType, TVariant<Ts...>>) GetValue<FSelectedType>() = Forward<T>(InValue);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
new (&Value) SelectedType(Forward<T>(InValue));
|
new (&Value) FSelectedType(Forward<T>(InValue));
|
||||||
TypeIndex = TVariantIndex<SelectedType, TVariant<Ts...>>;
|
TypeIndex = TVariantIndex<FSelectedType, TVariant<Ts...>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@ -299,8 +299,8 @@ public:
|
|||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
|
|
||||||
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
|
using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
|
||||||
SelectedType* Result = new (&Value) SelectedType(Forward<Us>(Args)...);
|
FSelectedType* Result = new (&Value) FSelectedType(Forward<Us>(Args)...);
|
||||||
TypeIndex = I;
|
TypeIndex = I;
|
||||||
|
|
||||||
return *Result;
|
return *Result;
|
||||||
@ -327,8 +327,8 @@ public:
|
|||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
|
|
||||||
using SelectedType = TVariantAlternative<I, TVariant<Ts...>>;
|
using FSelectedType = TVariantAlternative<I, TVariant<Ts...>>;
|
||||||
SelectedType* Result = new (&Value) SelectedType(IL, Forward<Us>(Args)...);
|
FSelectedType* Result = new (&Value) FSelectedType(IL, Forward<Us>(Args)...);
|
||||||
TypeIndex = I;
|
TypeIndex = I;
|
||||||
|
|
||||||
return *Result;
|
return *Result;
|
||||||
@ -448,7 +448,7 @@ NAMESPACE_PRIVATE_BEGIN
|
|||||||
template <typename F, typename... VariantTypes>
|
template <typename F, typename... VariantTypes>
|
||||||
struct TVariantVisitImpl
|
struct TVariantVisitImpl
|
||||||
{
|
{
|
||||||
struct GetTotalNum
|
struct FGetTotalNum
|
||||||
{
|
{
|
||||||
FORCEINLINE static constexpr size_t Do()
|
FORCEINLINE static constexpr size_t Do()
|
||||||
{
|
{
|
||||||
@ -464,10 +464,10 @@ struct TVariantVisitImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EncodeIndices
|
struct FEncodeIndices
|
||||||
{
|
{
|
||||||
FORCEINLINE static constexpr size_t Do(initializer_list<size_t> Indices)
|
FORCEINLINE static constexpr size_t Do(initializer_list<size_t> Indices)
|
||||||
{
|
{
|
||||||
@ -482,10 +482,10 @@ struct TVariantVisitImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DecodeExtent
|
struct FDecodeExtent
|
||||||
{
|
{
|
||||||
FORCEINLINE static constexpr size_t Do(size_t EncodedIndex, size_t Extent)
|
FORCEINLINE static constexpr size_t Do(size_t EncodedIndex, size_t Extent)
|
||||||
{
|
{
|
||||||
@ -497,76 +497,76 @@ struct TVariantVisitImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
return EncodedIndex % VariantNums[Extent];
|
return EncodedIndex % VariantNums[Extent];
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <size_t EncodedIndex, typename>
|
template <size_t EncodedIndex, typename>
|
||||||
struct InvokeEncoded;
|
struct FInvokeEncoded;
|
||||||
|
|
||||||
template <size_t EncodedIndex, size_t... ExtentIndices>
|
template <size_t EncodedIndex, size_t... ExtentIndices>
|
||||||
struct InvokeEncoded<EncodedIndex, TIndexSequence<ExtentIndices...>>
|
struct FInvokeEncoded<EncodedIndex, TIndexSequence<ExtentIndices...>>
|
||||||
{
|
{
|
||||||
FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants)
|
FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants)
|
||||||
{
|
{
|
||||||
return Invoke(Forward<F>(Func), Forward<VariantTypes>(Variants).template GetValue<DecodeExtent::Do(EncodedIndex, ExtentIndices)>()...);
|
return Invoke(Forward<F>(Func), Forward<VariantTypes>(Variants).template GetValue<FDecodeExtent::Do(EncodedIndex, ExtentIndices)>()...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ret>
|
template <typename Ret>
|
||||||
struct Result
|
struct FResult
|
||||||
{
|
{
|
||||||
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants)
|
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants)
|
||||||
{
|
{
|
||||||
return InvokeResult<Ret>(Forward<F>(Func), Forward<VariantTypes>(Variants).template GetValue<DecodeExtent::Do(EncodedIndex, ExtentIndices)>()...);
|
return InvokeResult<Ret>(Forward<F>(Func), Forward<VariantTypes>(Variants).template GetValue<FDecodeExtent::Do(EncodedIndex, ExtentIndices)>()...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename>
|
template <typename>
|
||||||
struct InvokeVariant;
|
struct FInvokeVariant;
|
||||||
|
|
||||||
template <size_t... EncodedIndices>
|
template <size_t... EncodedIndices>
|
||||||
struct InvokeVariant<TIndexSequence<EncodedIndices...>>
|
struct FInvokeVariant<TIndexSequence<EncodedIndices...>>
|
||||||
{
|
{
|
||||||
FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants)
|
FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants)
|
||||||
{
|
{
|
||||||
using ExtentIndices = TIndexSequenceFor<VariantTypes...>;
|
using FExtentIndices = TIndexSequenceFor<VariantTypes...>;
|
||||||
|
|
||||||
using ResultType = TCommonType<decltype(InvokeEncoded<EncodedIndices, ExtentIndices>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...))...>;
|
using FResultType = TCommonType<decltype(FInvokeEncoded<EncodedIndices, FExtentIndices>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...))...>;
|
||||||
|
|
||||||
using InvokeImplType = ResultType(*)(F&&, VariantTypes&&...);
|
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 Result
|
struct FResult
|
||||||
{
|
{
|
||||||
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants)
|
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants)
|
||||||
{
|
{
|
||||||
using ExtentIndices = TIndexSequenceFor<VariantTypes...>;
|
using FExtentIndices = TIndexSequenceFor<VariantTypes...>;
|
||||||
|
|
||||||
using InvokeImplType = Ret(*)(F&&, VariantTypes&&...);
|
using FInvokeImplType = Ret(*)(F&&, VariantTypes&&...);
|
||||||
|
|
||||||
constexpr InvokeImplType InvokeImpl[] = { InvokeEncoded<EncodedIndices, ExtentIndices>::template Result<Ret>::Do... };
|
constexpr FInvokeImplType InvokeImpl[] = { FInvokeEncoded<EncodedIndices, FExtentIndices>::template FResult<Ret>::Do... };
|
||||||
|
|
||||||
return InvokeImpl[EncodeIndices::Do({ Variants.GetIndex()... })](Forward<F>(Func), Forward<VariantTypes>(Variants)...);
|
return InvokeImpl[FEncodeIndices::Do({ Variants.GetIndex()... })](Forward<F>(Func), Forward<VariantTypes>(Variants)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants)
|
FORCEINLINE static constexpr decltype(auto) Do(F&& Func, VariantTypes&&... Variants)
|
||||||
{
|
{
|
||||||
return InvokeVariant<TMakeIndexSequence<GetTotalNum::Do()>>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...);
|
return FInvokeVariant<TMakeIndexSequence<FGetTotalNum::Do()>>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ret>
|
template <typename Ret>
|
||||||
struct Result
|
struct FResult
|
||||||
{
|
{
|
||||||
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants)
|
FORCEINLINE static constexpr Ret Do(F&& Func, VariantTypes&&... Variants)
|
||||||
{
|
{
|
||||||
return InvokeVariant<TMakeIndexSequence<GetTotalNum::Do()>>::template Result<Ret>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...);
|
return FInvokeVariant<TMakeIndexSequence<FGetTotalNum::Do()>>::template FResult<Ret>::Do(Forward<F>(Func), Forward<VariantTypes>(Variants)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -588,7 +588,7 @@ template <typename Ret, typename F, typename FirstVariantType, typename... Varia
|
|||||||
constexpr Ret Visit(F&& Func, FirstVariantType&& FirstVariant, VariantTypes&&... Variants)
|
constexpr Ret Visit(F&& Func, FirstVariantType&& FirstVariant, VariantTypes&&... Variants)
|
||||||
{
|
{
|
||||||
checkf((true && ... && Variants.IsValid()), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid()."));
|
checkf((true && ... && Variants.IsValid()), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid()."));
|
||||||
return NAMESPACE_PRIVATE::TVariantVisitImpl<F, FirstVariantType, VariantTypes...>::template Result<Ret>::Do(Forward<F>(Func), Forward<FirstVariantType>(FirstVariant), Forward<VariantTypes>(Variants)...);
|
return NAMESPACE_PRIVATE::TVariantVisitImpl<F, FirstVariantType, VariantTypes...>::template FResult<Ret>::Do(Forward<F>(Func), Forward<FirstVariantType>(FirstVariant), Forward<VariantTypes>(Variants)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
|
@ -20,58 +20,58 @@ template <typename T, typename U, template <typename> typename TQualifiers, temp
|
|||||||
|
|
||||||
NAMESPACE_PRIVATE_BEGIN
|
NAMESPACE_PRIVATE_BEGIN
|
||||||
|
|
||||||
// Template class declaration for the common Type implementation
|
// Template class declaration for the common type implementation
|
||||||
template <typename...>
|
template <typename...>
|
||||||
struct TCommonTypeImpl;
|
struct TCommonTypeImpl;
|
||||||
|
|
||||||
// If sizeof...(Ts) is zero, there is no member Type
|
// If sizeof...(Ts) is zero, there is no member FType
|
||||||
template <>
|
template <>
|
||||||
struct TCommonTypeImpl<> { };
|
struct TCommonTypeImpl<> { };
|
||||||
|
|
||||||
// If sizeof...(Ts) is one, the member Type names the same Type as TCommonType<T, T> if it exists; otherwise there is no member Type
|
// If sizeof...(Ts) is one, the member FType names the same type as TCommonType<T, T> if it exists; otherwise there is no member FType
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct TCommonTypeImpl<T> : TCommonTypeImpl<T, T> { };
|
struct TCommonTypeImpl<T> : TCommonTypeImpl<T, T> { };
|
||||||
|
|
||||||
// If sizeof...(Ts) is two
|
// If sizeof...(Ts) is two
|
||||||
|
|
||||||
// If applying TDecay to at least one of T and U produces a different Type, the member Type names the same Type as TCommonType<TDecay<T>, TDecay<U>>, if it exists; if not, there is no member Type
|
// If applying TDecay to at least one of T and U produces a different type, the member FType names the same type as TCommonType<TDecay<T>, TDecay<U>>, if it exists; if not, there is no member FType
|
||||||
template <typename T, typename U> concept CDecayed = CSameAs<T, TDecay<T>> && CSameAs<U, TDecay<U>>;
|
template <typename T, typename U> concept CDecayed = CSameAs<T, TDecay<T>> && CSameAs<U, TDecay<U>>;
|
||||||
template <typename T, typename U> requires (!CDecayed<T, U>)
|
template <typename T, typename U> requires (!CDecayed<T, U>)
|
||||||
struct TCommonTypeImpl<T, U> : TCommonTypeImpl<TDecay<T>, TDecay<U>> { };
|
struct TCommonTypeImpl<T, U> : TCommonTypeImpl<TDecay<T>, TDecay<U>> { };
|
||||||
|
|
||||||
// Otherwise, if there is a user specialization for TBasicCommonType<T, U>::Type, that specialization is used
|
// Otherwise, if there is a user specialization for TBasicCommonType<T, U>::FType, that specialization is used
|
||||||
template <typename T, typename U> concept CBasicCommonType = requires { typename TBasicCommonType<T, U>::Type; };
|
template <typename T, typename U> concept CBasicCommonType = requires { typename TBasicCommonType<T, U>::FType; };
|
||||||
template <typename T, typename U> requires (CDecayed<T, U> && CBasicCommonType<T, U>)
|
template <typename T, typename U> requires (CDecayed<T, U> && CBasicCommonType<T, U>)
|
||||||
struct TCommonTypeImpl<T, U> : TBasicCommonType<T, U>
|
struct TCommonTypeImpl<T, U> : TBasicCommonType<T, U>
|
||||||
{
|
{
|
||||||
// If such a specialization has a member named type,
|
// If such a specialization has a member named type,
|
||||||
// it must be a public and unambiguous member that names a cv-unqualified non-reference type to which both T and U are explicitly convertible
|
// it must be a public and unambiguous member that names a cv-unqualified non-reference type to which both T and U are explicitly convertible
|
||||||
// Additionally, TBasicCommonType<T, U>::Type and TBasicCommonType<U, T>::Type must denote the same type
|
// Additionally, TBasicCommonType<T, U>::FType and TBasicCommonType<U, T>::FType must denote the same type
|
||||||
static_assert(CSameAs<typename TBasicCommonType<T, U>::Type, TDecay<typename TBasicCommonType<T, U>::Type>>, "The basic common type must be a cv-unqualified non-reference type");
|
static_assert(CSameAs<typename TBasicCommonType<T, U>::FType, TDecay<typename TBasicCommonType<T, U>::FType>>, "The basic common type must be a cv-unqualified non-reference type");
|
||||||
static_assert(CConstructibleFrom<typename TBasicCommonType<T, U>::Type, T&&> && CConstructibleFrom<typename TBasicCommonType<T, U>::Type, U&&>, "The basic common type must be a type which both T and U are explicitly convertible");
|
static_assert(CConstructibleFrom<typename TBasicCommonType<T, U>::FType, T&&> && CConstructibleFrom<typename TBasicCommonType<T, U>::FType, U&&>, "The basic common type must be a type which both T and U are explicitly convertible");
|
||||||
static_assert(CSameAs<typename TBasicCommonType<T, U>::Type, typename TBasicCommonType<U, T>::Type>, "TBasicCommonType<T, U>::Type and TBasicCommonType<U, T>::Type must denote the same type");
|
static_assert(CSameAs<typename TBasicCommonType<T, U>::FType, typename TBasicCommonType<U, T>::FType>, "TBasicCommonType<T, U>::FType and TBasicCommonType<U, T>::FType must denote the same type");
|
||||||
};
|
};
|
||||||
|
|
||||||
// Otherwise, if TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())> is a valid Type, the member Type denotes that Type
|
// Otherwise, if TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())> is a valid type, the member FType denotes that type
|
||||||
template <typename T, typename U> concept CConditionalType = requires { typename TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())>; };
|
template <typename T, typename U> concept CConditionalType = requires { typename TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())>; };
|
||||||
template <typename T, typename U> requires (CDecayed<T, U> && !CBasicCommonType<T, U> && CConditionalType<T, U>)
|
template <typename T, typename U> requires (CDecayed<T, U> && !CBasicCommonType<T, U> && CConditionalType<T, U>)
|
||||||
struct TCommonTypeImpl<T, U> { using Type = TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())>; };
|
struct TCommonTypeImpl<T, U> { using FType = TDecay<decltype(false ? DeclVal<T>() : DeclVal<U>())>; };
|
||||||
|
|
||||||
// Otherwise, if TDecay<decltype(false ? DeclVal<CRT>() : DeclVal<CRU>())> is a valid Type,
|
// Otherwise, if TDecay<decltype(false ? DeclVal<CRT>() : DeclVal<CRU>())> is a valid type,
|
||||||
// where CRT and CRU are const TRemoveReference<T>& and const TRemoveReference<U>& respectively, the member Type denotes that Type
|
// where CRT and CRU are const TRemoveReference<T>& and const TRemoveReference<U>& respectively, the member FType denotes that type
|
||||||
template <typename T, typename U> concept CConditionalCRefType = requires { typename TDecay<decltype(false ? DeclVal<const TRemoveReference<T>&>() : DeclVal<const TRemoveReference<U>&>())>; };
|
template <typename T, typename U> concept CConditionalCRefType = requires { typename TDecay<decltype(false ? DeclVal<const TRemoveReference<T>&>() : DeclVal<const TRemoveReference<U>&>())>; };
|
||||||
template <typename T, typename U> requires (CDecayed<T, U> && !CBasicCommonType<T, U> && !CConditionalType<T, U> && CConditionalCRefType<T, U>)
|
template <typename T, typename U> requires (CDecayed<T, U> && !CBasicCommonType<T, U> && !CConditionalType<T, U> && CConditionalCRefType<T, U>)
|
||||||
struct TCommonTypeImpl<T, U> { using Type = TDecay<decltype(false ? DeclVal<const TRemoveReference<T>&>() : DeclVal<const TRemoveReference<U>&>())>; };
|
struct TCommonTypeImpl<T, U> { using FType = TDecay<decltype(false ? DeclVal<const TRemoveReference<T>&>() : DeclVal<const TRemoveReference<U>&>())>; };
|
||||||
|
|
||||||
// Otherwise, there is no member Type
|
// Otherwise, there is no member FType
|
||||||
|
|
||||||
// If sizeof...(Ts) is greater than two
|
// If sizeof...(Ts) is greater than two
|
||||||
|
|
||||||
// If TCommonType<T, U> exists, the member Type denotes TCommonType<TCommonType<T, U>, R...> if such a Type exists
|
// If TCommonType<T, U> exists, the member FType denotes TCommonType<TCommonType<T, U>, R...> if such a type exists
|
||||||
template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonTypeImpl<T, U>::Type; })
|
template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonTypeImpl<T, U>::FType; })
|
||||||
struct TCommonTypeImpl<T, U, W, Ts...> : TCommonTypeImpl<typename TCommonTypeImpl<T, U>::Type, W, Ts...> { };
|
struct TCommonTypeImpl<T, U, W, Ts...> : TCommonTypeImpl<typename TCommonTypeImpl<T, U>::FType, W, Ts...> { };
|
||||||
|
|
||||||
// In all other cases, there is no member Type
|
// In all other cases, there is no member FType
|
||||||
template <typename...>
|
template <typename...>
|
||||||
struct TCommonTypeImpl { };
|
struct TCommonTypeImpl { };
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ NAMESPACE_PRIVATE_BEGIN
|
|||||||
template <typename...>
|
template <typename...>
|
||||||
struct TCommonReferenceImpl;
|
struct TCommonReferenceImpl;
|
||||||
|
|
||||||
// Template class declaration for the simple common reference Type implementation
|
// Template class declaration for the simple common reference type implementation
|
||||||
template <typename, typename>
|
template <typename, typename>
|
||||||
struct TSimpleCommonReferenceImpl;
|
struct TSimpleCommonReferenceImpl;
|
||||||
|
|
||||||
@ -91,89 +91,89 @@ struct TSimpleCommonReferenceImpl;
|
|||||||
template <typename>
|
template <typename>
|
||||||
struct TQualifiersImpl;
|
struct TQualifiersImpl;
|
||||||
|
|
||||||
// If sizeof...(T) is zero, there is no member Type
|
// If sizeof...(T) is zero, there is no member FType
|
||||||
template <>
|
template <>
|
||||||
struct TCommonReferenceImpl<> { };
|
struct TCommonReferenceImpl<> { };
|
||||||
|
|
||||||
// If sizeof...(T) is one, the member Type names the same Type as T
|
// If sizeof...(T) is one, the member FType names the same type as T
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct TCommonReferenceImpl<T> { using Type = T; };
|
struct TCommonReferenceImpl<T> { using FType = T; };
|
||||||
|
|
||||||
// If sizeof...(Ts) is two
|
// If sizeof...(Ts) is two
|
||||||
|
|
||||||
// If T and U are both reference types, and the simple common reference Type S of T and U exists, then the member Type Type names S
|
// If T and U are both reference types, and the simple common reference type S of T and U exists, then the member FType names S
|
||||||
template <typename T, typename U> concept CSimpleCommonReference = requires { typename TSimpleCommonReferenceImpl<T, U>::Type; };
|
template <typename T, typename U> concept CSimpleCommonReference = requires { typename TSimpleCommonReferenceImpl<T, U>::FType; };
|
||||||
template <typename T, typename U> requires (CSimpleCommonReference<T, U>)
|
template <typename T, typename U> requires (CSimpleCommonReference<T, U>)
|
||||||
struct TCommonReferenceImpl<T, U> : TSimpleCommonReferenceImpl<T, U> { };
|
struct TCommonReferenceImpl<T, U> : TSimpleCommonReferenceImpl<T, U> { };
|
||||||
|
|
||||||
// Otherwise, if TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQ, UQ>::Type exists
|
// Otherwise, if TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQ, UQ>::FType exists
|
||||||
template <typename T, typename U> struct TBasicCommonReferenceImpl : TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQualifiersImpl<T>::template Apply, TQualifiersImpl<U>::template Apply> { };
|
template <typename T, typename U> struct TBasicCommonReferenceImpl : TBasicCommonReference<TRemoveCVRef<T>, TRemoveCVRef<U>, TQualifiersImpl<T>::template FApply, TQualifiersImpl<U>::template FApply> { };
|
||||||
template <typename T, typename U> concept CBasicCommonReference = requires { typename TBasicCommonReferenceImpl<T, U>::Type; };
|
template <typename T, typename U> concept CBasicCommonReference = requires { typename TBasicCommonReferenceImpl<T, U>::FType; };
|
||||||
template <typename T, typename U> requires (!CSimpleCommonReference<T, U> && CBasicCommonReference<T, U>)
|
template <typename T, typename U> requires (!CSimpleCommonReference<T, U> && CBasicCommonReference<T, U>)
|
||||||
struct TCommonReferenceImpl<T, U> : TBasicCommonReferenceImpl<T, U>
|
struct TCommonReferenceImpl<T, U> : TBasicCommonReferenceImpl<T, U>
|
||||||
{
|
{
|
||||||
// If such a specialization has a member named type,
|
// If such a specialization has a member named type,
|
||||||
// it must be a public and unambiguous member that names a type to which both TQualifiers<T> and UQualifiers<U> are convertible
|
// it must be a public and unambiguous member that names a type to which both TQualifiers<T> and UQualifiers<U> are convertible
|
||||||
// Additionally, TBasicCommonReference<T, U, TQualifiers, UQualifiers>::Type and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::Type must denote the same type
|
// Additionally, TBasicCommonReference<T, U, TQualifiers, UQualifiers>::FType and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::FType must denote the same type
|
||||||
static_assert(CConvertibleTo<T, typename TBasicCommonReferenceImpl<T, U>::Type> && CConvertibleTo<U, typename TBasicCommonReferenceImpl<T, U>::Type>, "The basic common reference must be a type to which both TQualifiers<T> and UQualifiers<U> are convertible");
|
static_assert(CConvertibleTo<T, typename TBasicCommonReferenceImpl<T, U>::FType> && CConvertibleTo<U, typename TBasicCommonReferenceImpl<T, U>::FType>, "The basic common reference must be a type to which both TQualifiers<T> and UQualifiers<U> are convertible");
|
||||||
static_assert(CSameAs<typename TBasicCommonReferenceImpl<T, U>::Type, typename TBasicCommonReferenceImpl<U, T>::Type>, "TBasicCommonReference<T, U, TQualifiers, UQualifiers>::Type and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::Type must denote the same type");
|
static_assert(CSameAs<typename TBasicCommonReferenceImpl<T, U>::FType, typename TBasicCommonReferenceImpl<U, T>::FType>, "TBasicCommonReference<T, U, TQualifiers, UQualifiers>::FType and TBasicCommonReference<U, T, UQualifiers, TQualifiers>::FType must denote the same type");
|
||||||
};
|
};
|
||||||
|
|
||||||
// Where TQ and UQ is a unary alias template such that TQ<U> is U with the addition of T's cv-ref qualifiers, then the member Type Type names that Type
|
// Where TQ and UQ is a unary alias template such that TQ<U> is U with the addition of T's cv-ref qualifiers, then the member FType names that type
|
||||||
template <typename T> struct TQualifiersImpl { template <typename U> using Apply = TCopyCV<T, U>; };
|
template <typename T> struct TQualifiersImpl { template <typename U> using FApply = TCopyCV<T, U>; };
|
||||||
template <typename T> struct TQualifiersImpl<T&> { template <typename U> using Apply = TAddLValueReference<TCopyCV<T, U>>; };
|
template <typename T> struct TQualifiersImpl<T&> { template <typename U> using FApply = TAddLValueReference<TCopyCV<T, U>>; };
|
||||||
template <typename T> struct TQualifiersImpl<T&&> { template <typename U> using Apply = TAddRValueReference<TCopyCV<T, U>>; };
|
template <typename T> struct TQualifiersImpl<T&&> { template <typename U> using FApply = TAddRValueReference<TCopyCV<T, U>>; };
|
||||||
|
|
||||||
// Otherwise, if decltype(false ? Val<T>() : Val<U>()), where val is a function template template <typename T> T Val();, is a valid Type, then the member Type Type names that Type
|
// Otherwise, if decltype(false ? Val<T>() : Val<U>()), where val is a function template <typename T> T Val();, is a valid type, then the member FType names that type
|
||||||
template <typename T> T Val();
|
template <typename T> T Val();
|
||||||
template <typename T, typename U> concept CConditionalValType = requires { typename TVoid<decltype(false ? Val<T>() : Val<U>())>; };
|
template <typename T, typename U> concept CConditionalValType = requires { typename TVoid<decltype(false ? Val<T>() : Val<U>())>; };
|
||||||
template <typename T, typename U> requires (!CSimpleCommonReference<T, U> && !CBasicCommonReference<T, U> && CConditionalValType<T, U>)
|
template <typename T, typename U> requires (!CSimpleCommonReference<T, U> && !CBasicCommonReference<T, U> && CConditionalValType<T, U>)
|
||||||
struct TCommonReferenceImpl<T, U> { using Type = decltype(false ? Val<T>() : Val<U>()); };
|
struct TCommonReferenceImpl<T, U> { using FType = decltype(false ? Val<T>() : Val<U>()); };
|
||||||
|
|
||||||
// Otherwise, if TCommonType<T, U> is a valid Type, then the member Type Type names that Type
|
// Otherwise, if TCommonType<T, U> is a valid type, then the member FType names that type
|
||||||
template <typename T, typename U> concept CCommonTypeImpl = requires { typename TCommonTypeImpl<T, U>; };
|
template <typename T, typename U> concept CCommonTypeImpl = requires { typename TCommonTypeImpl<T, U>; };
|
||||||
template <typename T, typename U> requires (!CSimpleCommonReference<T, U> && !CBasicCommonReference<T, U> && !CConditionalValType<T, U> && CCommonTypeImpl<T, U>)
|
template <typename T, typename U> requires (!CSimpleCommonReference<T, U> && !CBasicCommonReference<T, U> && !CConditionalValType<T, U> && CCommonTypeImpl<T, U>)
|
||||||
struct TCommonReferenceImpl<T, U> : TCommonTypeImpl<T, U> { };
|
struct TCommonReferenceImpl<T, U> : TCommonTypeImpl<T, U> { };
|
||||||
|
|
||||||
// Otherwise, there is no member Type
|
// Otherwise, there is no member FType
|
||||||
|
|
||||||
// If sizeof...(Ts) is greater than two
|
// If sizeof...(Ts) is greater than two
|
||||||
|
|
||||||
// If TCommonReference<T, U> exists, the member Type denotes TCommonReference<TCommonReference<T, U>, R...> if such a Type exists
|
// If TCommonReference<T, U> exists, the member FType denotes TCommonReference<TCommonReference<T, U>, R...> if such a type exists
|
||||||
template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonReferenceImpl<T, U>::Type; })
|
template <typename T, typename U, typename W, typename... Ts> requires (requires { typename TCommonReferenceImpl<T, U>::FType; })
|
||||||
struct TCommonReferenceImpl<T, U, W, Ts...> : TCommonReferenceImpl<typename TCommonReferenceImpl<T, U>::Type, W, Ts...> { };
|
struct TCommonReferenceImpl<T, U, W, Ts...> : TCommonReferenceImpl<typename TCommonReferenceImpl<T, U>::FType, W, Ts...> { };
|
||||||
|
|
||||||
// In all other cases, there is no member Type
|
// In all other cases, there is no member FType
|
||||||
template <typename...>
|
template <typename...>
|
||||||
struct TCommonReferenceImpl { };
|
struct TCommonReferenceImpl { };
|
||||||
|
|
||||||
// If T is CV1 X & and U is CV2 Y & (i.e., both are lvalue reference types):
|
// If T is CV1 X & and U is CV2 Y & (i.e., both are lvalue reference types):
|
||||||
// their simple common reference Type is decltype(false ? DeclVal<CV12 X &>() : DeclVal<CV12 Y &>()),
|
// their simple common reference type is decltype(false ? DeclVal<CV12 X &>() : DeclVal<CV12 Y &>()),
|
||||||
// where CV12 is the union of CV1 and CV2, if that Type exists and is a reference Type
|
// where CV12 is the union of CV1 and CV2, if that type exists and is a reference type
|
||||||
template <typename T, typename U> requires (CLValueReference<decltype(false ? DeclVal<TCopyCV<T, U>&>() : DeclVal<TCopyCV<U, T>&>())>)
|
template <typename T, typename U> requires (CLValueReference<decltype(false ? DeclVal<TCopyCV<T, U>&>() : DeclVal<TCopyCV<U, T>&>())>)
|
||||||
struct TSimpleCommonReferenceImpl<T&, U&> { using Type = decltype(false ? DeclVal<TCopyCV<T, U>&>() : DeclVal<TCopyCV<U, T>&>()); };
|
struct TSimpleCommonReferenceImpl<T&, U&> { using FType = decltype(false ? DeclVal<TCopyCV<T, U>&>() : DeclVal<TCopyCV<U, T>&>()); };
|
||||||
|
|
||||||
// If T and U are both rvalue reference types:
|
// If T and U are both rvalue reference types:
|
||||||
// if the simple common reference Type of T & and U & exists, then let C denote that Type's corresponding rvalue reference Type
|
// if the simple common reference type of T & and U & exists, then let C denote that type's corresponding rvalue reference type
|
||||||
// If CConvertibleTo<T, C> and CConvertibleTo<U, C> are both true, then the simple common reference Type of T and U is C
|
// If CConvertibleTo<T, C> and CConvertibleTo<U, C> are both true, then the simple common reference type of T and U is C
|
||||||
template <typename T, typename U> requires (CConvertibleTo<T&&, TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::Type> &&> && CConvertibleTo<U&&, TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::Type> &&>)
|
template <typename T, typename U> requires (CConvertibleTo<T&&, TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::FType> &&> && CConvertibleTo<U&&, TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::FType> &&>)
|
||||||
struct TSimpleCommonReferenceImpl<T&&, U&&> { using Type = TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::Type> &&; };
|
struct TSimpleCommonReferenceImpl<T&&, U&&> { using FType = TRemoveReference<typename TSimpleCommonReferenceImpl<T&, U&>::FType> &&; };
|
||||||
|
|
||||||
// Otherwise, one of the two types must be an lvalue reference Type A & and the other must be an rvalue reference Type B &&
|
// Otherwise, one of the two types must be a lvalue reference type A & and the other must be a rvalue reference type B &&
|
||||||
// Let D denote the simple common reference Type of A & and B const &, if any
|
// Let D denote the simple common reference type of A & and B const &, if any
|
||||||
// If D exists and CConvertibleTo<B&&, D> is true, then the simple common reference Type is D
|
// If D exists and CConvertibleTo<B&&, D> is true, then the simple common reference type is D
|
||||||
template <typename T, typename U> requires (CConvertibleTo<U&&, typename TSimpleCommonReferenceImpl<T&, const U&>::Type>)
|
template <typename T, typename U> requires (CConvertibleTo<U&&, typename TSimpleCommonReferenceImpl<T&, const U&>::FType>)
|
||||||
struct TSimpleCommonReferenceImpl<T&, U&&> { using Type = typename TSimpleCommonReferenceImpl<T&, const U&>::Type; };
|
struct TSimpleCommonReferenceImpl<T&, U&&> { using FType = typename TSimpleCommonReferenceImpl<T&, const U&>::FType; };
|
||||||
template <typename T, typename U> struct TSimpleCommonReferenceImpl<T&&, U&> : TSimpleCommonReferenceImpl<U&, T&&> { }; // The order is not important
|
template <typename T, typename U> struct TSimpleCommonReferenceImpl<T&&, U&> : TSimpleCommonReferenceImpl<U&, T&&> { }; // The order is not important
|
||||||
|
|
||||||
// Otherwise, there's no simple common reference Type
|
// Otherwise, there's no simple common reference type
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
struct TSimpleCommonReferenceImpl { };
|
struct TSimpleCommonReferenceImpl { };
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
template <typename... Ts> using TCommonType = typename NAMESPACE_PRIVATE::TCommonTypeImpl<Ts...>::Type;
|
template <typename... Ts> using TCommonType = typename NAMESPACE_PRIVATE::TCommonTypeImpl<Ts...>::FType;
|
||||||
template <typename... Ts> using TCommonReference = typename NAMESPACE_PRIVATE::TCommonReferenceImpl<Ts...>::Type;
|
template <typename... Ts> using TCommonReference = typename NAMESPACE_PRIVATE::TCommonReferenceImpl<Ts...>::FType;
|
||||||
|
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
concept CCommonReference =
|
concept CCommonReference =
|
||||||
|
@ -11,35 +11,35 @@ NAMESPACE_MODULE_BEGIN(Utility)
|
|||||||
|
|
||||||
NAMESPACE_PRIVATE_BEGIN
|
NAMESPACE_PRIVATE_BEGIN
|
||||||
|
|
||||||
template <typename From, typename To> struct TCopyConstImpl { using Type = To; };
|
template <typename From, typename To> struct TCopyConstImpl { using FType = To; };
|
||||||
template <typename From, typename To> struct TCopyConstImpl<const From, To> { using Type = const To; };
|
template <typename From, typename To> struct TCopyConstImpl<const From, To> { using FType = const To; };
|
||||||
|
|
||||||
template <typename From, typename To> struct TCopyVolatileImpl { using Type = To; };
|
template <typename From, typename To> struct TCopyVolatileImpl { using FType = To; };
|
||||||
template <typename From, typename To> struct TCopyVolatileImpl<volatile From, To> { using Type = volatile To; };
|
template <typename From, typename To> struct TCopyVolatileImpl<volatile From, To> { using FType = volatile To; };
|
||||||
|
|
||||||
template <typename From, typename To> struct TCopyCVImpl { using Type = typename TCopyConstImpl<From, typename TCopyVolatileImpl<From, To>::Type>::Type; };
|
template <typename From, typename To> struct TCopyCVImpl { using FType = typename TCopyConstImpl<From, typename TCopyVolatileImpl<From, To>::FType>::FType; };
|
||||||
|
|
||||||
template <typename From, typename To> struct TCopyReferenceImpl { using Type = To; };
|
template <typename From, typename To> struct TCopyReferenceImpl { using FType = To; };
|
||||||
template <typename From, typename To> struct TCopyReferenceImpl<From&, To> { using Type = To&; };
|
template <typename From, typename To> struct TCopyReferenceImpl<From&, To> { using FType = To&; };
|
||||||
template <typename From, typename To> struct TCopyReferenceImpl<From&&, To> { using Type = To&&; };
|
template <typename From, typename To> struct TCopyReferenceImpl<From&&, To> { using FType = To&&; };
|
||||||
|
|
||||||
template <typename From, typename To> struct TCopyCVRefImpl { using Type = typename TCopyCVImpl<From, To>::Type; };
|
template <typename From, typename To> struct TCopyCVRefImpl { using FType = typename TCopyCVImpl<From, To>::FType; };
|
||||||
template <typename From, typename To> struct TCopyCVRefImpl<From, To& > { using Type = typename TCopyCVImpl<From, To>::Type&; };
|
template <typename From, typename To> struct TCopyCVRefImpl<From, To& > { using FType = typename TCopyCVImpl<From, To>::FType&; };
|
||||||
template <typename From, typename To> struct TCopyCVRefImpl<From, To&&> { using Type = typename TCopyCVImpl<From, To>::Type&&; };
|
template <typename From, typename To> struct TCopyCVRefImpl<From, To&&> { using FType = typename TCopyCVImpl<From, To>::FType&&; };
|
||||||
template <typename From, typename To> struct TCopyCVRefImpl<From&, To > { using Type = typename TCopyCVImpl<From, To>::Type&; };
|
template <typename From, typename To> struct TCopyCVRefImpl<From&, To > { using FType = typename TCopyCVImpl<From, To>::FType&; };
|
||||||
template <typename From, typename To> struct TCopyCVRefImpl<From&, To& > { using Type = typename TCopyCVImpl<From, To>::Type&; };
|
template <typename From, typename To> struct TCopyCVRefImpl<From&, To& > { using FType = typename TCopyCVImpl<From, To>::FType&; };
|
||||||
template <typename From, typename To> struct TCopyCVRefImpl<From&, To&&> { using Type = typename TCopyCVImpl<From, To>::Type&; };
|
template <typename From, typename To> struct TCopyCVRefImpl<From&, To&&> { using FType = typename TCopyCVImpl<From, To>::FType&; };
|
||||||
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To > { using Type = typename TCopyCVImpl<From, To>::Type&&; };
|
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To > { using FType = typename TCopyCVImpl<From, To>::FType&&; };
|
||||||
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To& > { using Type = typename TCopyCVImpl<From, To>::Type&; };
|
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To& > { using FType = typename TCopyCVImpl<From, To>::FType&; };
|
||||||
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To&&> { using Type = typename TCopyCVImpl<From, To>::Type&&; };
|
template <typename From, typename To> struct TCopyCVRefImpl<From&&, To&&> { using FType = typename TCopyCVImpl<From, To>::FType&&; };
|
||||||
|
|
||||||
NAMESPACE_PRIVATE_END
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
template <typename From, typename To> using TCopyConst = typename NAMESPACE_PRIVATE::TCopyConstImpl<From, To>::Type;
|
template <typename From, typename To> using TCopyConst = typename NAMESPACE_PRIVATE::TCopyConstImpl <From, To>::FType;
|
||||||
template <typename From, typename To> using TCopyVolatile = typename NAMESPACE_PRIVATE::TCopyVolatileImpl<From, To>::Type;
|
template <typename From, typename To> using TCopyVolatile = typename NAMESPACE_PRIVATE::TCopyVolatileImpl <From, To>::FType;
|
||||||
template <typename From, typename To> using TCopyCV = typename NAMESPACE_PRIVATE::TCopyCVImpl<From, To>::Type;
|
template <typename From, typename To> using TCopyCV = typename NAMESPACE_PRIVATE::TCopyCVImpl <From, To>::FType;
|
||||||
template <typename From, typename To> using TCopyReference = typename NAMESPACE_PRIVATE::TCopyReferenceImpl<From, To>::Type;
|
template <typename From, typename To> using TCopyReference = typename NAMESPACE_PRIVATE::TCopyReferenceImpl<From, To>::FType;
|
||||||
template <typename From, typename To> using TCopyCVRef = typename NAMESPACE_PRIVATE::TCopyCVRefImpl<From, To>::Type;
|
template <typename From, typename To> using TCopyCVRef = typename NAMESPACE_PRIVATE::TCopyCVRefImpl <From, To>::FType;
|
||||||
|
|
||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
NAMESPACE_MODULE_END(Redcraft)
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
|
@ -6,14 +6,14 @@ NAMESPACE_REDCRAFT_BEGIN
|
|||||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||||
NAMESPACE_MODULE_BEGIN(Utility)
|
NAMESPACE_MODULE_BEGIN(Utility)
|
||||||
|
|
||||||
template <typename InType, InType InValue>
|
template <typename T, T InValue>
|
||||||
struct TConstant
|
struct TConstant
|
||||||
{
|
{
|
||||||
using ValueType = InType;
|
using FValueType = T;
|
||||||
using Type = TConstant;
|
using FType = TConstant;
|
||||||
static constexpr ValueType Value = InValue;
|
static constexpr FValueType Value = InValue;
|
||||||
FORCEINLINE constexpr operator ValueType() const { return Value; }
|
FORCEINLINE constexpr operator FValueType() const { return Value; }
|
||||||
FORCEINLINE constexpr ValueType operator()() const { return Value; }
|
FORCEINLINE constexpr FValueType operator()() const { return Value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <bool InValue>
|
template <bool InValue>
|
||||||
|
Loading…
Reference in New Issue
Block a user