Compare commits

..

4 Commits

25 changed files with 515 additions and 662 deletions

View File

@ -1,16 +1,15 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Range.h"
#include "Memory/Allocator.h" #include "Memory/Allocator.h"
#include "Iterator/Iterator.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "Templates/TypeHash.h" #include "Templates/TypeHash.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
#include "Miscellaneous/Compare.h" #include "Miscellaneous/Compare.h"
#include "Memory/MemoryOperator.h" #include "Memory/MemoryOperator.h"
#include "Miscellaneous/Iterator.h"
#include "Miscellaneous/Container.h"
#include "Miscellaneous/AssertionMacros.h" #include "Miscellaneous/AssertionMacros.h"
#include "Miscellaneous/ConstantIterator.h"
NAMESPACE_REDCRAFT_BEGIN NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Redcraft)
@ -57,18 +56,24 @@ public:
/** Constructs the container with 'Count' copies of elements with 'InValue'. */ /** Constructs the container with 'Count' copies of elements with 'InValue'. */
TArray(size_t Count, const FElementType& InValue) requires (CCopyConstructible<FElementType>) TArray(size_t Count, const FElementType& InValue) requires (CCopyConstructible<FElementType>)
: TArray(MakeCountedConstantIterator(InValue, Count), DefaultSentinel) : TArray(Range::Repeat(InValue, Count))
{ } { }
/** Constructs the container with the contents of the range ['First', 'Last'). */ /** Constructs the container with the contents of the range ['First', 'Last'). */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>> && CMovable<FElementType>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReference<I>> && CMovable<FElementType>)
TArray(I First, S Last) TArray(I First, S Last)
{ {
if constexpr (CForwardIterator<I>) if constexpr (CForwardIterator<I>)
{ {
if constexpr (CSizedSentinelFor<S, I>) { checkf(First - Last <= 0, TEXT("Illegal range iterator. Please check First <= Last.")); } size_t Count = 0;
const size_t Count = Iteration::Distance(First, Last); if constexpr (CSizedSentinelFor<S, I>)
{
checkf(First - Last <= 0, TEXT("Illegal range iterator. Please check First <= Last."));
Count = Last - First;
}
else for (I Iter = First; Iter != Last; ++Iter) ++Count;
Impl.ArrayNum = Count; Impl.ArrayNum = Count;
Impl.ArrayMax = Impl->CalculateSlackReserve(Num()); Impl.ArrayMax = Impl->CalculateSlackReserve(Num());
@ -93,6 +98,10 @@ public:
} }
} }
/** Constructs the container with the contents of the range. */
template <CInputRange R> requires (!CSameAs<TRemoveCVRef<R>, TArray> && CConstructibleFrom<FElementType, TRangeReference<R>> && CMovable<FElementType>)
FORCEINLINE explicit TArray(R&& Range) : TArray(Range::Begin(Range), Range::End(Range)) { }
/** Copy constructor. Constructs the container with the copy of the contents of 'InValue'. */ /** Copy constructor. Constructs the container with the copy of the contents of 'InValue'. */
TArray(const TArray& InValue) requires (CCopyConstructible<FElementType>) TArray(const TArray& InValue) requires (CCopyConstructible<FElementType>)
{ {
@ -129,7 +138,7 @@ public:
} }
/** Constructs the container with the contents of the initializer list. */ /** Constructs the container with the contents of the initializer list. */
FORCEINLINE TArray(initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) : TArray(Iteration::Begin(IL), Iteration::End(IL)) { } FORCEINLINE TArray(initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) : TArray(Range::Begin(IL), Range::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()
@ -243,38 +252,38 @@ public:
/** Replaces the contents with those identified by initializer list. */ /** Replaces the contents with those identified by initializer list. */
TArray& operator=(initializer_list<FElementType> IL) requires (CCopyable<FElementType>) TArray& operator=(initializer_list<FElementType> IL) requires (CCopyable<FElementType>)
{ {
size_t NumToAllocate = GetNum(IL); size_t NumToAllocate = Range::Num(IL);
NumToAllocate = NumToAllocate > Max() ? Impl->CalculateSlackGrow(GetNum(IL), Max()) : NumToAllocate; NumToAllocate = NumToAllocate > Max() ? Impl->CalculateSlackGrow (Range::Num(IL), Max()) : NumToAllocate;
NumToAllocate = NumToAllocate < Max() ? Impl->CalculateSlackShrink(GetNum(IL), Max()) : NumToAllocate; NumToAllocate = NumToAllocate < Max() ? Impl->CalculateSlackShrink(Range::Num(IL), Max()) : NumToAllocate;
if (NumToAllocate != Max()) if (NumToAllocate != Max())
{ {
Memory::Destruct(Impl.Pointer, Num()); Memory::Destruct(Impl.Pointer, Num());
Impl->Deallocate(Impl.Pointer); Impl->Deallocate(Impl.Pointer);
Impl.ArrayNum = GetNum(IL); Impl.ArrayNum = Range::Num(IL);
Impl.ArrayMax = NumToAllocate; Impl.ArrayMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(Max()); Impl.Pointer = Impl->Allocate(Max());
Memory::CopyConstruct<FElementType>(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), Num()); Memory::CopyConstruct<FElementType>(Impl.Pointer, Range::GetData(IL), Num());
return *this; return *this;
} }
if (GetNum(IL) <= Num()) if (Range::Num(IL) <= Num())
{ {
Memory::CopyAssign(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), GetNum(IL)); Memory::CopyAssign(Impl.Pointer, Range::GetData(IL), Range::Num(IL));
Memory::Destruct(Impl.Pointer + GetNum(IL), Num() - GetNum(IL)); Memory::Destruct(Impl.Pointer + Range::Num(IL), Num() - Range::Num(IL));
} }
else if (GetNum(IL) <= Max()) else if (Range::Num(IL) <= Max())
{ {
Memory::CopyAssign(Impl.Pointer, NAMESPACE_REDCRAFT::GetData(IL), Num()); Memory::CopyAssign(Impl.Pointer, Range::GetData(IL), Num());
Memory::CopyConstruct<FElementType>(Impl.Pointer + Num(), NAMESPACE_REDCRAFT::GetData(IL) + Num(), GetNum(IL) - Num()); Memory::CopyConstruct<FElementType>(Impl.Pointer + Num(), Range::GetData(IL) + Num(), Range::Num(IL) - Num());
} }
else check_no_entry(); else check_no_entry();
Impl.ArrayNum = GetNum(IL); Impl.ArrayNum = Range::Num(IL);
return *this; return *this;
} }
@ -406,22 +415,29 @@ public:
{ {
checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator().")); checkf(IsValidIterator(Iter), TEXT("Read access violation. Please check IsValidIterator()."));
return Insert(Iter, MakeCountedConstantIterator(InValue, Count), DefaultSentinel); return Insert(Iter, Range::Repeat(InValue, Count));
} }
/** Inserts elements from range ['First', 'Last') before 'Iter'. */ /** Inserts elements from range ['First', 'Last') before 'Iter'. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>> template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReference<I>>
&& CAssignableFrom<FElementType&, TIteratorReferenceType<I>> && CMovable<FElementType>) && CAssignableFrom<FElementType&, TIteratorReference<I>> && CMovable<FElementType>)
FIterator Insert(FConstIterator 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()."));
if constexpr (CForwardIterator<I>) if constexpr (CForwardIterator<I>)
{ {
if constexpr (CSizedSentinelFor<S, I>) { checkf(First - Last <= 0, TEXT("Illegal range iterator. Please check First <= Last.")); }
const size_t InsertIndex = Iter - Begin(); const size_t InsertIndex = Iter - Begin();
const size_t Count = Iteration::Distance(First, Last);
size_t Count = 0;
if constexpr (CSizedSentinelFor<S, I>)
{
checkf(First - Last <= 0, TEXT("Illegal range iterator. Please check First <= Last."));
Count = Last - First;
}
else for (I Jter = First; Jter != Last; ++Jter) ++Count;
if (Count == 0) return FIterator(this, Impl.Pointer + InsertIndex); if (Count == 0) return FIterator(this, Impl.Pointer + InsertIndex);
@ -523,10 +539,18 @@ public:
} }
} }
/** Inserts elements from range before 'Iter'. */
template <CInputRange R> requires (CConstructibleFrom<FElementType, TRangeReference<R>>
&& CAssignableFrom<FElementType&, TRangeReference<R>> && CMovable<FElementType>)
FORCEINLINE FIterator Insert(FConstIterator Iter, R&& Range)
{
return Insert(Iter, Range::Begin(Range), Range::End(Range));
}
/** Inserts elements from initializer list before 'Iter' in the container. */ /** Inserts elements from initializer list before 'Iter' in the container. */
FORCEINLINE FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL) requires (CCopyable<FElementType>) FORCEINLINE FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL) requires (CCopyable<FElementType>)
{ {
return Insert(Iter, Iteration::Begin(IL), Iteration::End(IL)); return Insert(Iter, Range::Begin(IL), Range::End(IL));
} }
/** Inserts a new element into the container directly before 'Iter'. */ /** Inserts a new element into the container directly before 'Iter'. */
@ -1058,7 +1082,10 @@ private:
}; };
template <typename I, typename S> template <typename I, typename S>
TArray(I, S) -> TArray<TIteratorElementType<I>>; TArray(I, S) -> TArray<TIteratorElement<I>>;
template <typename R>
TArray(R) -> TArray<TRangeElement<R>>;
template <typename T> template <typename T>
TArray(initializer_list<T>) -> TArray<T>; TArray(initializer_list<T>) -> TArray<T>;

View File

@ -1,16 +1,16 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Range.h"
#include "Memory/Address.h" #include "Memory/Address.h"
#include "Memory/Allocator.h" #include "Memory/Allocator.h"
#include "Containers/Array.h" #include "Containers/Array.h"
#include "Iterator/Iterator.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "Templates/TypeHash.h" #include "Templates/TypeHash.h"
#include "Containers/StaticArray.h" #include "Containers/StaticArray.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
#include "Miscellaneous/Compare.h" #include "Miscellaneous/Compare.h"
#include "Miscellaneous/Iterator.h"
#include "Miscellaneous/Container.h"
#include "Miscellaneous/AssertionMacros.h" #include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN NAMESPACE_REDCRAFT_BEGIN
@ -29,7 +29,7 @@ class TArrayView
{ {
public: public:
using FElementType = T; using FElementType = TRemoveCV<T>;
using FReference = T&; using FReference = T&;
@ -53,7 +53,7 @@ public:
} }
/** Constructs an array view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */ /** Constructs an array view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */
template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], FElementType(*)[]>) template <CContiguousIterator I> requires (CConvertibleTo<TIteratorReference<I>, T> && CSameAs<TRemoveCVRef<TIteratorReference<I>>, TRemoveCVRef<T>>)
FORCEINLINE constexpr explicit (Extent != DynamicExtent) TArrayView(I InFirst, size_t InCount) FORCEINLINE constexpr explicit (Extent != DynamicExtent) TArrayView(I InFirst, size_t InCount)
{ {
checkf(Extent == DynamicExtent || Extent == InCount, TEXT("Illegal range count. Please check InCount.")); checkf(Extent == DynamicExtent || Extent == InCount, TEXT("Illegal range count. Please check InCount."));
@ -67,7 +67,7 @@ public:
} }
/** Constructs an array view that is a view over the range ['InFirst', 'InLast'). */ /** Constructs an array view that is a view over the range ['InFirst', 'InLast'). */
template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorElementType<I>(*)[], FElementType(*)[]>) template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorReference<I>, T> && CSameAs<TRemoveCVRef<TIteratorReference<I>>, TRemoveCVRef<T>>)
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."));
@ -156,36 +156,36 @@ public:
/** Obtains an array view that is a view over the first 'Count' elements of this array view. */ /** Obtains an array view that is a view over the first 'Count' elements of this array view. */
template <size_t Count> requires (Extent == DynamicExtent || Extent >= Count) template <size_t Count> requires (Extent == DynamicExtent || Extent >= Count)
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, Count> First() const NODISCARD FORCEINLINE constexpr TArrayView<T, Count> First() const
{ {
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count.")); checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
return TArrayView<FElementType, Count>(Begin(), Count); return TArrayView<T, Count>(Begin(), Count);
} }
/** Obtains an array view that is a view over the first 'Count' elements of this array view. */ /** Obtains an array view that is a view over the first 'Count' elements of this array view. */
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, DynamicExtent> First(size_t Count) const NODISCARD FORCEINLINE constexpr TArrayView<T, DynamicExtent> First(size_t Count) const
{ {
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count.")); checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
return TArrayView<FElementType, DynamicExtent>(Begin(), Count); return TArrayView<T, DynamicExtent>(Begin(), Count);
} }
/** Obtains an array view that is a view over the last 'Count' elements of this array view. */ /** Obtains an array view that is a view over the last 'Count' elements of this array view. */
template <size_t Count> requires (Extent == DynamicExtent || Extent >= Count) template <size_t Count> requires (Extent == DynamicExtent || Extent >= Count)
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, Count> Last() const NODISCARD FORCEINLINE constexpr TArrayView<T, Count> Last() const
{ {
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count.")); checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
return TArrayView<FElementType, Count>(End() - Count, Count); return TArrayView<T, Count>(End() - Count, Count);
} }
/** Obtains an array view that is a view over the last 'Count' elements of this array view. */ /** Obtains an array view that is a view over the last 'Count' elements of this array view. */
NODISCARD FORCEINLINE constexpr TArrayView<FElementType, DynamicExtent> Last(size_t Count) const NODISCARD FORCEINLINE constexpr TArrayView<T, DynamicExtent> Last(size_t Count) const
{ {
checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count.")); checkf(Count <= Num(), TEXT("Illegal subview range. Please check Count."));
return TArrayView<FElementType, DynamicExtent>(End() - Count, Count); return TArrayView<T, DynamicExtent>(End() - Count, Count);
} }
/** Obtains an array view that is a view over the 'Count' elements of this array view starting at 'Offset'. */ /** Obtains an array view that is a view over the 'Count' elements of this array view starting at 'Offset'. */
@ -198,11 +198,11 @@ public:
if constexpr (Count != DynamicExtent) if constexpr (Count != DynamicExtent)
{ {
return TArrayView<FElementType, SubviewExtent>(Begin() + Offset, Count); return TArrayView<T, SubviewExtent>(Begin() + Offset, Count);
} }
else else
{ {
return TArrayView<FElementType, SubviewExtent>(Begin() + Offset, Num() - Offset); return TArrayView<T, SubviewExtent>(Begin() + Offset, Num() - Offset);
} }
} }
@ -213,11 +213,11 @@ public:
if (Count != DynamicExtent) if (Count != DynamicExtent)
{ {
return TArrayView<FElementType, DynamicExtent>(Begin() + Offset, Count); return TArrayView<T, DynamicExtent>(Begin() + Offset, Count);
} }
else else
{ {
return TArrayView<FElementType, DynamicExtent>(Begin() + Offset, Num() - Offset); return TArrayView<T, DynamicExtent>(Begin() + Offset, Num() - Offset);
} }
} }
@ -245,7 +245,7 @@ public:
} }
/** @return The pointer to the underlying element storage. */ /** @return The pointer to the underlying element storage. */
NODISCARD FORCEINLINE constexpr FElementType* GetData() const { return Impl.Pointer; } NODISCARD FORCEINLINE constexpr T* GetData() const { return Impl.Pointer; }
/** @return The iterator to the first or end element. */ /** @return The iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr FIterator Begin() const { return FIterator(this, Impl.Pointer); } NODISCARD FORCEINLINE constexpr FIterator Begin() const { return FIterator(this, Impl.Pointer); }
@ -291,7 +291,7 @@ public:
private: private:
struct FImplWithoutNum { FElementType* Pointer; }; struct FImplWithoutNum { T* Pointer; };
struct FImplWithNum : FImplWithoutNum { size_t ArrayNum; }; struct FImplWithNum : FImplWithoutNum { size_t ArrayNum; };
@ -367,7 +367,7 @@ public:
}; };
template <typename I, typename S> template <typename I, typename S>
TArrayView(I, S) -> TArrayView<TRemoveReference<TIteratorReferenceType<I>>>; TArrayView(I, S) -> TArrayView<TRemoveReference<TIteratorReference<I>>>;
template <typename T, size_t N> template <typename T, size_t N>
TArrayView(T(&)[N]) -> TArrayView<T, N>; TArrayView(T(&)[N]) -> TArrayView<T, N>;

View File

@ -1,16 +1,16 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Range.h"
#include "Memory/Memory.h" #include "Memory/Memory.h"
#include "Memory/Allocator.h" #include "Memory/Allocator.h"
#include "Iterator/Iterator.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "Templates/TypeHash.h" #include "Templates/TypeHash.h"
#include "Templates/Noncopyable.h" #include "Templates/Noncopyable.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
#include "Miscellaneous/Compare.h" #include "Miscellaneous/Compare.h"
#include "Memory/MemoryOperator.h" #include "Memory/MemoryOperator.h"
#include "Miscellaneous/Iterator.h"
#include "Miscellaneous/Container.h"
#include "Miscellaneous/AssertionMacros.h" #include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN NAMESPACE_REDCRAFT_BEGIN
@ -101,16 +101,22 @@ public:
} }
/** Constructs the bitset with the bits of the range ['First', 'Last'). */ /** Constructs the bitset with the bits of the range ['First', 'Last'). */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<bool, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<bool, TIteratorReference<I>>)
TBitset(I First, S Last) TBitset(I First, S Last)
{ {
if constexpr (CForwardIterator<I>) if constexpr (CForwardIterator<I>)
{ {
if constexpr (CSizedSentinelFor<S, I>) { checkf(First - Last <= 0, TEXT("Illegal range iterator. Please check First <= Last.")); } size_t Count = 0;
const size_t InCount = Iteration::Distance(First, Last); if constexpr (CSizedSentinelFor<S, I>)
{
checkf(First - Last <= 0, TEXT("Illegal range iterator. Please check First <= Last."));
new (this) TBitset(InCount); Count = Last - First;
}
else for (I Iter = First; Iter != Last; ++Iter) ++Count;
new (this) TBitset(Count);
for (FReference Ref: *this) Ref = *First++; for (FReference Ref: *this) Ref = *First++;
} }
@ -126,6 +132,10 @@ public:
} }
} }
/** Constructs the bitset with the bits of the range. */
template <CInputRange R> requires (!CSameAs<TRemoveCVRef<R>, TBitset> && CConstructibleFrom<bool, TRangeReference<R>>)
FORCEINLINE explicit TBitset(R&& Range) : TBitset(Range::Begin(Range), Range::End(Range)) { }
/** Copy constructor. Constructs the bitset with the copy of the bits of 'InValue'. */ /** Copy constructor. Constructs the bitset with the copy of the bits of 'InValue'. */
FORCEINLINE TBitset(const TBitset& InValue) FORCEINLINE TBitset(const TBitset& InValue)
{ {
@ -160,7 +170,7 @@ public:
} }
/** Constructs the bitset with the bits of the initializer list. */ /** Constructs the bitset with the bits of the initializer list. */
FORCEINLINE TBitset(initializer_list<bool> IL) : TBitset(Iteration::Begin(IL), Iteration::End(IL)) { } FORCEINLINE TBitset(initializer_list<bool> IL) : TBitset(Range::Begin(IL), Range::End(IL)) { }
/** Destructs the bitset. The storage is deallocated. */ /** Destructs the bitset. The storage is deallocated. */
~TBitset() ~TBitset()
@ -228,9 +238,9 @@ public:
/** Replaces the bits with those identified by initializer list. */ /** Replaces the bits with those identified by initializer list. */
TBitset& operator=(initializer_list<bool> IL) TBitset& operator=(initializer_list<bool> IL)
{ {
auto First = Iteration::Begin(IL); auto First = Range::Begin(IL);
const size_t BlocksCount = (GetNum(IL) + BlockWidth - 1) / BlockWidth; const size_t BlocksCount = (Range::Num(IL) + BlockWidth - 1) / BlockWidth;
size_t NumToAllocate = BlocksCount; size_t NumToAllocate = BlocksCount;
@ -241,7 +251,7 @@ public:
{ {
Impl->Deallocate(Impl.Pointer); Impl->Deallocate(Impl.Pointer);
Impl.BitsetNum = GetNum(IL); Impl.BitsetNum = Range::Num(IL);
Impl.BlocksMax = NumToAllocate; Impl.BlocksMax = NumToAllocate;
Impl.Pointer = Impl->Allocate(MaxBlocks()); Impl.Pointer = Impl->Allocate(MaxBlocks());
@ -250,7 +260,7 @@ public:
return *this; return *this;
} }
Impl.BitsetNum = GetNum(IL); Impl.BitsetNum = Range::Num(IL);
for (FReference Ref : *this) Ref = *First++; for (FReference Ref : *this) Ref = *First++;

View File

@ -1,16 +1,15 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Range.h"
#include "Memory/Allocator.h" #include "Memory/Allocator.h"
#include "Iterator/Iterator.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "Templates/TypeHash.h" #include "Templates/TypeHash.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
#include "Miscellaneous/Compare.h" #include "Miscellaneous/Compare.h"
#include "Memory/MemoryOperator.h" #include "Memory/MemoryOperator.h"
#include "Miscellaneous/Iterator.h"
#include "Miscellaneous/Container.h"
#include "Miscellaneous/AssertionMacros.h" #include "Miscellaneous/AssertionMacros.h"
#include "Miscellaneous/ConstantIterator.h"
NAMESPACE_REDCRAFT_BEGIN NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Redcraft)
@ -76,11 +75,11 @@ public:
/** Constructs the container with 'Count' copies of elements with 'InValue'. */ /** Constructs the container with 'Count' copies of elements with 'InValue'. */
TList(size_t Count, const FElementType& InValue) requires (CCopyable<FElementType>) TList(size_t Count, const FElementType& InValue) requires (CCopyable<FElementType>)
: TList(MakeCountedConstantIterator(InValue, Count), DefaultSentinel) : TList(Range::Repeat(InValue, Count))
{ } { }
/** Constructs the container with the contents of the range ['First', 'Last'). */ /** Constructs the container with the contents of the range ['First', 'Last'). */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReference<I>>)
TList(I First, S Last) : TList() TList(I First, S Last) : TList()
{ {
FNode* EndNode = Impl.HeadNode->PrevNode; FNode* EndNode = Impl.HeadNode->PrevNode;
@ -101,6 +100,10 @@ public:
Impl.HeadNode->PrevNode = EndNode; Impl.HeadNode->PrevNode = EndNode;
} }
/** Constructs the container with the contents of the range. */
template <CInputRange R> requires (!CSameAs<TRemoveCVRef<R>, TList> && CConstructibleFrom<FElementType, TRangeReference<R>>)
FORCEINLINE explicit TList(R&& Range) : TList(Range::Begin(Range), Range::End(Range)) { }
/** Copy constructor. Constructs the container with the copy of the contents of 'InValue'. */ /** Copy constructor. Constructs the container with the copy of the contents of 'InValue'. */
FORCEINLINE TList(const TList& InValue) requires (CCopyConstructible<FElementType>) : TList(InValue.Begin(), InValue.End()) { } FORCEINLINE TList(const TList& InValue) requires (CCopyConstructible<FElementType>) : TList(InValue.Begin(), InValue.End()) { }
@ -108,7 +111,7 @@ public:
FORCEINLINE TList(TList&& InValue) : TList() { Swap(*this, InValue); } FORCEINLINE TList(TList&& InValue) : TList() { Swap(*this, InValue); }
/** Constructs the container with the contents of the initializer list. */ /** Constructs the container with the contents of the initializer list. */
FORCEINLINE TList(initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) : TList(Iteration::Begin(IL), Iteration::End(IL)) { } FORCEINLINE TList(initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) : TList(Range::Begin(IL), Range::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()
@ -168,10 +171,10 @@ public:
/** Replaces the contents with those identified by initializer list. */ /** Replaces the contents with those identified by initializer list. */
TList& operator=(initializer_list<FElementType> IL) requires (CCopyable<FElementType>) TList& operator=(initializer_list<FElementType> IL) requires (CCopyable<FElementType>)
{ {
FIterator ThisIter = Begin(); FIterator ThisIter = Begin();
const FElementType* OtherIter = Iteration::Begin(IL); const FElementType* OtherIter = Range::Begin(IL);
while (ThisIter != End() && OtherIter != Iteration::End(IL)) while (ThisIter != End() && OtherIter != Range::End(IL))
{ {
*ThisIter = *OtherIter; *ThisIter = *OtherIter;
@ -181,18 +184,18 @@ public:
if (ThisIter == End()) if (ThisIter == End())
{ {
while (OtherIter != Iteration::End(IL)) while (OtherIter != Range::End(IL))
{ {
EmplaceBack(*OtherIter); EmplaceBack(*OtherIter);
++OtherIter; ++OtherIter;
} }
} }
else if (OtherIter == Iteration::End(IL)) else if (OtherIter == Range::End(IL))
{ {
Erase(ThisIter, End()); Erase(ThisIter, End());
} }
Impl.ListNum = GetNum(IL); Impl.ListNum = Range::Num(IL);
return *this; return *this;
} }
@ -244,11 +247,11 @@ public:
/** Inserts 'Count' copies of the 'InValue' before 'Iter' in the container. */ /** Inserts 'Count' copies of the 'InValue' before 'Iter' in the container. */
FIterator Insert(FConstIterator Iter, size_t Count, const FElementType& InValue) requires (CCopyConstructible<FElementType>) FIterator Insert(FConstIterator Iter, size_t Count, const FElementType& InValue) requires (CCopyConstructible<FElementType>)
{ {
return Insert(Iter, MakeCountedConstantIterator(InValue, Count), DefaultSentinel); return Insert(Iter, Range::Repeat(InValue, Count));
} }
/** Inserts elements from range ['First', 'Last') before 'Iter'. */ /** Inserts elements from range ['First', 'Last') before 'Iter'. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReference<I>>)
FIterator Insert(FConstIterator Iter, I First, S Last) FIterator Insert(FConstIterator Iter, I First, S Last)
{ {
if (First == Last) return FIterator(Iter.Pointer); if (First == Last) return FIterator(Iter.Pointer);
@ -282,8 +285,12 @@ public:
return FIterator(FirstNode); return FIterator(FirstNode);
} }
/** Inserts elements from range ['First', 'Last') before 'Iter'. */
template <CInputRange R> requires (CConstructibleFrom<FElementType, TRangeReference<R>>)
FORCEINLINE FIterator Insert(FConstIterator Iter, R&& Range) { return Insert(Iter, Range::Begin(Range), Range::End(Range)); }
/** Inserts elements from initializer list before 'Iter' in the container. */ /** Inserts elements from initializer list before 'Iter' in the container. */
FORCEINLINE FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) { return Insert(Iter, Iteration::Begin(IL), Iteration::End(IL)); } FORCEINLINE FIterator Insert(FConstIterator Iter, initializer_list<FElementType> IL) requires (CCopyConstructible<FElementType>) { return Insert(Iter, Range::Begin(IL), Range::End(IL)); }
/** Inserts a new element into the container directly before 'Iter'. */ /** Inserts a new element into the container directly before 'Iter'. */
template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...>) template <typename... Ts> requires (CConstructibleFrom<FElementType, Ts...>)
@ -381,7 +388,7 @@ public:
{ {
FIterator First = End(); FIterator First = End();
Iteration::Advance(First, Count - Impl.ListNum); for (size_t Index = 0; Index != Impl.ListNum - Count; ++Index) --First;
Erase(First, End()); Erase(First, End());
@ -417,7 +424,7 @@ public:
{ {
FIterator First = End(); FIterator First = End();
Iteration::Advance(First, Count - Impl.ListNum); for (size_t Index = 0; Index != Impl.ListNum - Count; ++Index) --First;
Erase(First, End()); Erase(First, End());
@ -598,7 +605,10 @@ private:
}; };
template <typename I, typename S> template <typename I, typename S>
TList(I, S) -> TList<TIteratorElementType<I>>; TList(I, S) -> TList<TIteratorElement<I>>;
template <typename R>
TList(R) -> TList<TRangeElement<R>>;
template <typename T> template <typename T>
TList(initializer_list<T>) -> TList<T>; TList(initializer_list<T>) -> TList<T>;

View File

@ -1,13 +1,13 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Range.h"
#include "Templates/Meta.h" #include "Templates/Meta.h"
#include "Iterator/Iterator.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "Templates/TypeHash.h" #include "Templates/TypeHash.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
#include "Miscellaneous/Compare.h" #include "Miscellaneous/Compare.h"
#include "Miscellaneous/Iterator.h"
#include "Miscellaneous/Container.h"
#include "Miscellaneous/AssertionMacros.h" #include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN NAMESPACE_REDCRAFT_BEGIN

View File

@ -1,14 +1,14 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Range.h"
#include "Iterator/Iterator.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "Templates/TypeHash.h" #include "Templates/TypeHash.h"
#include "Templates/Noncopyable.h" #include "Templates/Noncopyable.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
#include "Miscellaneous/Compare.h" #include "Miscellaneous/Compare.h"
#include "Memory/MemoryOperator.h" #include "Memory/MemoryOperator.h"
#include "Miscellaneous/Iterator.h"
#include "Miscellaneous/Container.h"
#include "Miscellaneous/AssertionMacros.h" #include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN NAMESPACE_REDCRAFT_BEGIN

View File

@ -1,226 +0,0 @@
#pragma once
#include "CoreTypes.h"
#include "Memory/Address.h"
#include "Templates/Utility.h"
#include "Miscellaneous/Iterator.h"
#include "Miscellaneous/Compare.h"
#include "TypeTraits/TypeTraits.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
/** An iterator that always points to the same value. */
template <typename T> requires (CDestructible<T> || CLValueReference<T>)
class TConstantIterator final
{
public:
using FElementType = TRemoveCV<T>;
FORCEINLINE constexpr TConstantIterator() = default;
FORCEINLINE constexpr ~TConstantIterator() = default;
template <typename U = T> requires (!CSameAs<TConstantIterator, TRemoveCVRef<U>> && CConstructibleFrom<T, U&&>)
FORCEINLINE constexpr explicit TConstantIterator(U&& InValue) : Value(Forward<U>(InValue)) { }
template <typename U> requires (CConstructibleFrom<T, const U&>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const U&, T>) TConstantIterator(const TConstantIterator<U>& InValue) : Value(InValue.Value) { }
template <typename U> requires (CConstructibleFrom<T, U&&>)
FORCEINLINE constexpr explicit (!CConvertibleTo<U&&, T>) TConstantIterator(TConstantIterator<U>&& InValue) : Value(MoveTemp(InValue.Value)) { }
FORCEINLINE constexpr TConstantIterator(const TConstantIterator&) requires (CCopyConstructible<T>) = default;
FORCEINLINE constexpr TConstantIterator(TConstantIterator&&) requires (CMoveConstructible<T>) = default;
template <typename U> requires (CConvertibleTo<const U&, T> && CAssignableFrom<T&, const U&>)
FORCEINLINE constexpr TConstantIterator& operator=(const TConstantIterator<U>& InValue) { Value = InValue.Value; return *this; }
template <typename U> requires (CConvertibleTo<U&&, T> && CAssignableFrom<T&, U&&>)
FORCEINLINE constexpr TConstantIterator& operator=(TConstantIterator<U>&& InValue) { Value = MoveTemp(InValue.Value); return *this; }
FORCEINLINE constexpr TConstantIterator& operator=(const TConstantIterator&) requires (CCopyAssignable<T>) = default;
FORCEINLINE constexpr TConstantIterator& operator=(TConstantIterator&&) requires (CMoveAssignable<T>) = default;
NODISCARD FORCEINLINE constexpr const T& operator*() const { return Value; }
NODISCARD FORCEINLINE constexpr const T* operator->() const { return AddressOf(Value); }
FORCEINLINE constexpr TConstantIterator& operator++() { return *this; }
FORCEINLINE constexpr void operator++(int) { }
private:
T Value;
template <typename U> requires (CDestructible<U> || CLValueReference<U>)
friend class TConstantIterator;
};
static_assert(CInputIterator<TConstantIterator<int>>);
/** An iterator that always points to the same value. */
template <typename T>
class TConstantIterator<T&> final
{
public:
using FElementType = TRemoveCV<T>;
FORCEINLINE constexpr TConstantIterator() = default;
FORCEINLINE constexpr TConstantIterator(const TConstantIterator&) = default;
FORCEINLINE constexpr TConstantIterator(TConstantIterator&&) = default;
FORCEINLINE constexpr TConstantIterator& operator=(const TConstantIterator&) = default;
FORCEINLINE constexpr TConstantIterator& operator=(TConstantIterator&&) = default;
FORCEINLINE constexpr ~TConstantIterator() = default;
FORCEINLINE constexpr explicit TConstantIterator(const T& InValue) : Ptr(AddressOf(InValue)) { }
FORCEINLINE constexpr explicit TConstantIterator(const T&& InValue) = delete;
template <typename U> requires (CConvertibleTo<U*, T*>)
FORCEINLINE constexpr TConstantIterator(const TConstantIterator<U>& InValue) : Ptr(InValue.Ptr) { }
template <typename U> requires (CConvertibleTo<U*, T*>)
FORCEINLINE constexpr TConstantIterator& operator=(const TConstantIterator<U>& InValue) { Ptr = InValue.Ptr; return *this; }
NODISCARD FORCEINLINE constexpr const T& operator*() const { return *Ptr; }
NODISCARD FORCEINLINE constexpr const T* operator->() const { return Ptr; }
FORCEINLINE constexpr TConstantIterator& operator++() { return *this; }
FORCEINLINE constexpr void operator++(int) { }
private:
const T* Ptr;
template <typename U> requires (CDestructible<U> || CLValueReference<U>)
friend class TConstantIterator;
};
static_assert(CInputIterator<TConstantIterator<int&>>);
/** An iterator adapter specialization that tracks the distance of a constant iterator to the end of the range. */
template <typename T> requires (CDestructible<T> || CLValueReference<T>)
class TCountedIterator<TConstantIterator<T>> final
{
public:
using FIteratorType = TConstantIterator<T>;
using FElementType = typename TConstantIterator<T>::FElementType;
# if DO_CHECK
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<FIteratorType>) : Length(1), MaxLength(0) { }
# else
FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible<FIteratorType>) = default;
# endif
FORCEINLINE constexpr TCountedIterator(const TCountedIterator&) = default;
FORCEINLINE constexpr TCountedIterator(TCountedIterator&&) = default;
FORCEINLINE constexpr TCountedIterator& operator=(const TCountedIterator&) = default;
FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator&&) = default;
FORCEINLINE constexpr ~TCountedIterator() = default;
template <typename U = FIteratorType> requires (!CSameAs<TCountedIterator, TRemoveCVRef<U>> && CConstructibleFrom<FIteratorType, U>)
FORCEINLINE constexpr explicit TCountedIterator(U&& InValue, ptrdiff N) : Current(Forward<U>(InValue)), Length(N) { check_code({ MaxLength = N; }); }
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConstructibleFrom<FIteratorType, const J&>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const J&, FIteratorType>) TCountedIterator(const TCountedIterator<J>& InValue) : Current(InValue.Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConstructibleFrom<FIteratorType, J>)
FORCEINLINE constexpr explicit (!CConvertibleTo<J&&, FIteratorType>) TCountedIterator(TCountedIterator<J>&& InValue) : Current(MoveTemp(InValue).Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); }
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConvertibleTo<const J&, FIteratorType> && CAssignableFrom<FIteratorType&, const J&>)
FORCEINLINE constexpr TCountedIterator& operator=(const TCountedIterator<J>& InValue) { Current = InValue.Current; Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; }
template <CInputOrOutputIterator J> requires (!CSameAs<FIteratorType, J> && CConvertibleTo<J&&, FIteratorType> && CAssignableFrom<FIteratorType&, J&&>)
FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator<J>&& InValue) { Current = MoveTemp(InValue).Current; Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; }
template <CCommonType<FIteratorType> J>
NODISCARD friend FORCEINLINE constexpr bool operator==(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { return LHS.Length == RHS.Length; }
template <CCommonType<FIteratorType> J>
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { return LHS.Length <=> RHS.Length; }
NODISCARD FORCEINLINE constexpr bool operator==(FDefaultSentinel) const& { return Length == static_cast<ptrdiff>(0); }
NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(FDefaultSentinel) const& { return static_cast<ptrdiff>(0) <=> Length; }
NODISCARD FORCEINLINE constexpr const TRemoveReference<T>& operator*() const { CheckThis(true ); return *Current; }
NODISCARD FORCEINLINE constexpr const TRemoveReference<T>* operator->() const { CheckThis(false); return ToAddress(Current); }
NODISCARD FORCEINLINE constexpr const TRemoveReference<T>& operator[](ptrdiff) const { return *this; }
FORCEINLINE constexpr TCountedIterator& operator++() { --Length; CheckThis(); return *this; }
FORCEINLINE constexpr TCountedIterator& operator--() { ++Length; CheckThis(); return *this; }
FORCEINLINE constexpr TCountedIterator operator++(int) { TCountedIterator Temp = *this; --Length; CheckThis(); return Temp; }
FORCEINLINE constexpr TCountedIterator operator--(int) { TCountedIterator Temp = *this; ++Length; CheckThis(); return Temp; }
FORCEINLINE constexpr TCountedIterator& operator+=(ptrdiff Offset) { Length -= Offset; CheckThis(); return *this; }
FORCEINLINE constexpr TCountedIterator& operator-=(ptrdiff Offset) { Length += Offset; CheckThis(); return *this; }
NODISCARD friend FORCEINLINE constexpr TCountedIterator operator+(TCountedIterator Iter, ptrdiff Offset) { TCountedIterator Temp = Iter; Temp += Offset; return Temp; }
NODISCARD friend FORCEINLINE constexpr TCountedIterator operator+(ptrdiff Offset, TCountedIterator Iter) { TCountedIterator Temp = Iter; Temp += Offset; return Temp; }
NODISCARD FORCEINLINE constexpr TCountedIterator operator-(ptrdiff Offset) const { TCountedIterator Temp = *this; Temp -= Offset; return Temp; }
template <CCommonType<FIteratorType> J>
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, const TCountedIterator<J>& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Length - RHS.Length; }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { LHS.CheckThis(); return -LHS.Num(); }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { RHS.CheckThis(); return RHS.Num(); }
NODISCARD FORCEINLINE constexpr const FIteratorType& GetBase() const& { CheckThis(); return Current; }
NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { CheckThis(); return MoveTemp(Current); }
NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; }
private:
FIteratorType Current;
ptrdiff Length;
# if DO_CHECK
ptrdiff MaxLength;
# endif
FORCEINLINE void CheckThis(bool bExceptEnd = false) const
{
checkf(static_cast<ptrdiff>(0) <= Length && Length <= MaxLength, TEXT("Read access violation. Please check Num()."));
checkf(!(bExceptEnd && Length == static_cast<ptrdiff>(0)), TEXT("Read access violation. Please check Num()."));
}
template <CInputOrOutputIterator J>
friend class TCountedIterator;
};
static_assert(CRandomAccessIterator<TCountedIterator<TConstantIterator<int>>>);
static_assert(CSizedSentinelFor<FDefaultSentinel, TCountedIterator<TConstantIterator<int>>>);
template <typename T> requires (CDestructible<T> || CLValueReference<T>)
NODISCARD FORCEINLINE constexpr auto MakeConstantIterator(T&& Value)
{
return TConstantIterator<T>(Forward<T>(Value));
}
template <typename T> requires (CDestructible<T> || CLValueReference<T>)
NODISCARD FORCEINLINE constexpr auto MakeCountedConstantIterator(T&& Value, ptrdiff N)
{
return TCountedIterator<TConstantIterator<T>>(MakeConstantIterator(Forward<T>(Value)), N);
}
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -1,77 +0,0 @@
#pragma once
#include "CoreTypes.h"
#include "Templates/TypeHash.h"
#include "TypeTraits/Swappable.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
/** @return The pointer to the container element storage. */
template <typename T> requires (requires(T&& Container) { { Container.GetData() } -> CPointer; })
FORCEINLINE constexpr auto GetData(T&& Container)
{
return Container.GetData();
}
/** Overloads the GetData algorithm for arrays. */
template <typename T, size_t N> FORCEINLINE constexpr T* GetData( T(& Container)[N]) { return Container; }
template <typename T, size_t N> FORCEINLINE constexpr T* GetData( T(&& Container)[N]) { return Container; }
template <typename T, size_t N> FORCEINLINE constexpr const T* GetData(const T(& Container)[N]) { return Container; }
template <typename T, size_t N> FORCEINLINE constexpr const T* GetData(const T(&& Container)[N]) { return Container; }
/** Overloads the GetData algorithm for initializer_list. */
template <typename T>
FORCEINLINE constexpr const T* GetData(initializer_list<T> Container)
{
return Container.begin();
}
/** @return The number of elements in the container. */
template <typename T> requires (requires(T&& Container) { { Container.Num() } -> CConvertibleTo<size_t>; })
FORCEINLINE constexpr auto GetNum(T&& Container)
{
return Container.Num();
}
/** Overloads the GetNum algorithm for arrays. */
template <typename T, size_t N> FORCEINLINE constexpr size_t GetNum( T(& )[N]) { return N; }
template <typename T, size_t N> FORCEINLINE constexpr size_t GetNum( T(&&)[N]) { return N; }
template <typename T, size_t N> FORCEINLINE constexpr size_t GetNum(const T(& )[N]) { return N; }
template <typename T, size_t N> FORCEINLINE constexpr size_t GetNum(const T(&&)[N]) { return N; }
/** Overloads the GetNum algorithm for initializer_list. */
template <typename T>
FORCEINLINE constexpr size_t GetNum(initializer_list<T> Container)
{
return Container.size();
}
/** Overloads the Swap algorithm for arrays. */
template <typename T, size_t N> requires (CSwappable<TRemoveAllExtents<T>>)
FORCEINLINE constexpr void Swap(T(&A)[N], T(&B)[N])
{
for (size_t Index = 0; Index < N; ++Index)
{
Swap(A[Index], B[Index]);
}
}
/** Overloads the GetTypeHash algorithm for arrays. */
template <typename T, size_t N> requires (CHashable<TRemoveAllExtents<T>>)
FORCEINLINE constexpr size_t GetTypeHash(T(&A)[N])
{
size_t Result = 3516520171;
for (size_t Index = 0; Index < N; ++Index)
{
Result = HashCombine(Result, GetTypeHash(A[Index]));
}
return Result;
}
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -1,200 +0,0 @@
#pragma once
#include "CoreTypes.h"
#include "Iterator/Iterator.h"
#include "TypeTraits/TypeTraits.h"
#include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
template <typename I>
using TIteratorElementType = TIteratorElement<I>;
template <typename I>
using TIteratorPointerType = TIteratorPointer<I>;
template <CReferenceable I>
using TIteratorReferenceType = TIteratorReference<I>;
template <CReferenceable I> requires (requires(I& Iter) { { MoveTemp(*Iter) } -> CReferenceable; })
using TIteratorRValueReferenceType = TIteratorRValueReference<I>;
NAMESPACE_BEGIN(Iteration)
/** Increments given iterator 'Iter' by 'N' elements. */
template <CInputIterator I>
FORCEINLINE constexpr void Advance(I& Iter, ptrdiff N)
{
if constexpr (CRandomAccessIterator<I>)
{
Iter += N;
}
else if constexpr (CBidirectionalIterator<I>)
{
for (; N > 0; --N) ++Iter;
for (; N < 0; ++N) --Iter;
}
else
{
checkf(N >= 0, TEXT("The iterator must satisfy the CBidirectionalIterator in order to be decremented."));
for (; N > 0; --N) ++Iter;
}
}
/** @return The number of hops from 'First' to 'Last'. */
template <CInputIterator I, CSentinelFor<I> S>
FORCEINLINE constexpr ptrdiff Distance(I First, S Last)
{
if constexpr (CSizedSentinelFor<S, I>)
{
return Last - First;
}
else
{
ptrdiff Result = 0;
for (; First != Last; ++First) ++Result;
return Result;
}
}
/** @return The 'N'-th successor of iterator 'Iter'. */
template <CInputIterator I>
FORCEINLINE constexpr I Next(I Iter, TMakeUnsigned<ptrdiff> N = 1)
{
Iteration::Advance(Iter, N);
return Iter;
}
/** @return The 'N'-th predecessor of iterator 'Iter'. */
template <CBidirectionalIterator I>
FORCEINLINE constexpr I Prev(I Iter, TMakeUnsigned<ptrdiff> N = 1)
{
Iteration::Advance(Iter, -N);
return Iter;
}
NAMESPACE_END(Iteration)
template <CIndirectlyReadable J, CIndirectlyWritable<TIteratorReferenceType<J>> I>
FORCEINLINE void IndirectlyCopy(I&& Iter, J&& Jter)
{
*Iter = *Jter;
}
template <CIndirectlyReadable J, CIndirectlyWritable<TIteratorRValueReferenceType<J>> I>
FORCEINLINE void IndirectlyMove(I&& Iter, J&& Jter)
{
*Iter = MoveTemp(*Jter);
}
template <CIndirectlyReadable I, CIndirectlyReadable J> requires (CSwappable<TIteratorReferenceType<I>, TIteratorReferenceType<J>>)
FORCEINLINE void IndirectlySwap(I&& Iter, J&& Jter)
{
Swap(*Iter, *Jter);
}
template <typename I, typename J = I>
concept CIndirectlyCopyable = requires(const I Iter, const J Jter) { IndirectlyCopy(Iter, Jter); };
template <typename I, typename J = I>
concept CIndirectlyMovable = requires(const I Iter, const J Jter) { IndirectlyMove(Iter, Jter); };
template <typename I, typename J = I>
concept CIndirectlySwappable = CIndirectlyReadable<I> && CIndirectlyReadable<J>
&& requires(const I Iter, const J Jter)
{
IndirectlySwap(Iter, Iter);
IndirectlySwap(Jter, Jter);
IndirectlySwap(Iter, Jter);
IndirectlySwap(Jter, Iter);
};
NAMESPACE_BEGIN(Iteration)
/** @return The iterator to the beginning of a container. */
template <typename T> requires (requires(T&& Container) { { Container.Begin() } -> CForwardIterator; })
FORCEINLINE constexpr auto Begin(T&& Container)
{
return Container.Begin();
}
/** Overloads the Begin algorithm for arrays. */
template <typename T, size_t N> FORCEINLINE constexpr T* Begin( T(& Container)[N]) { return Container; }
template <typename T, size_t N> FORCEINLINE constexpr T* Begin( T(&& Container)[N]) { return Container; }
template <typename T, size_t N> FORCEINLINE constexpr const T* Begin(const T(& Container)[N]) { return Container; }
template <typename T, size_t N> FORCEINLINE constexpr const T* Begin(const T(&& Container)[N]) { return Container; }
/** Overloads the Begin algorithm for initializer_list. */
template <typename T>
FORCEINLINE constexpr auto Begin(initializer_list<T> Container)
{
return Container.begin();
}
/** @return The iterator to the end of a container. */
template <typename T> requires (requires(T&& Container) { { Container.End() } -> CForwardIterator; })
FORCEINLINE constexpr auto End(T&& Container)
{
return Container.End();
}
/** Overloads the End algorithm for arrays. */
template <typename T, size_t N> FORCEINLINE constexpr T* End( T(& Container)[N]) { return Container + N; }
template <typename T, size_t N> FORCEINLINE constexpr T* End( T(&& Container)[N]) { return Container + N; }
template <typename T, size_t N> FORCEINLINE constexpr const T* End(const T(& Container)[N]) { return Container + N; }
template <typename T, size_t N> FORCEINLINE constexpr const T* End(const T(&& Container)[N]) { return Container + N; }
/** Overloads the End algorithm for initializer_list. */
template <typename T>
FORCEINLINE constexpr auto End(initializer_list<T> Container)
{
return Container.end();
}
/** @return The reverse iterator to the beginning of a container. */
template <typename T> requires (requires(T&& Container) { { Container.RBegin() } -> CForwardIterator; })
FORCEINLINE constexpr auto RBegin(T&& Container)
{
return Container.RBegin();
}
/** Overloads the RBegin algorithm for arrays. */
template <typename T, size_t N> FORCEINLINE constexpr auto RBegin( T(& Container)[N]) { return TReverseIterator(End(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr auto RBegin( T(&& Container)[N]) { return TReverseIterator(End(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr auto RBegin(const T(& Container)[N]) { return TReverseIterator(End(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr auto RBegin(const T(&& Container)[N]) { return TReverseIterator(End(Container)); }
/** Overloads the RBegin algorithm for initializer_list. */
template <typename T>
FORCEINLINE constexpr auto RBegin(initializer_list<T> Container)
{
return TReverseIterator(Container.end());
}
/** @return The reverse iterator to the end of a container. */
template <typename T> requires (requires(T&& Container) { { Container.REnd() } -> CForwardIterator; })
FORCEINLINE constexpr auto REnd(T&& Container)
{
return Container.REnd();
}
/** Overloads the REnd algorithm for arrays. */
template <typename T, size_t N> FORCEINLINE constexpr auto REnd( T(& Container)[N]) { return TReverseIterator(Begin(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr auto REnd( T(&& Container)[N]) { return TReverseIterator(Begin(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr auto REnd(const T(& Container)[N]) { return TReverseIterator(Begin(Container)); }
template <typename T, size_t N> FORCEINLINE constexpr auto REnd(const T(&& Container)[N]) { return TReverseIterator(Begin(Container)); }
/** Overloads the REnd algorithm for initializer_list. */
template <typename T>
FORCEINLINE constexpr auto REnd(initializer_list<T> Container)
{
return TReverseIterator(Container.begin());
}
NAMESPACE_END(Iteration)
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -152,10 +152,12 @@ NODISCARD FORCEINLINE constexpr auto All(R&& InRange)
/** Creates A view adapter that includes all elements of a range. */ /** Creates A view adapter that includes all elements of a range. */
NODISCARD FORCEINLINE constexpr auto All() NODISCARD FORCEINLINE constexpr auto All()
{ {
return TAdaptorClosure([]<CViewableRange R> requires (requires { Range::All(DeclVal<R>()); }) (R&& Base) using FClosure = decltype([]<CViewableRange R> requires (requires { Range::All(DeclVal<R>()); }) (R&& Base)
{ {
return Range::All(Forward<R>(Base)); return Range::All(Forward<R>(Base));
}); });
return TAdaptorClosure<FClosure>();
} }
/** A view adapter that includes all elements of a range. */ /** A view adapter that includes all elements of a range. */

View File

@ -0,0 +1,163 @@
#pragma once
#include "CoreTypes.h"
#include "Range/View.h"
#include "Range/Utility.h"
#include "Range/AllView.h"
#include "Templates/Utility.h"
#include "Range/TransformView.h"
#include "TypeTraits/TypeTraits.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
// NOTE: In the STL, use std::from_range_t as a disambiguation tag that resolves ambiguity
// introduced by the list-initialization. For example, for the following code:
//
// R RangeOfInts = /* ... */;
// static_assert(CRange<R> and CSameAs<TRangeElement<R>, int>);
//
// TArray Arr(RangeOfInts);
// TArray Brr{RangeOfInts};
//
// If R is TArray<int> than decltype(Arr) is TArray<int> and decltype(Brr) is TArray<int>,
// otherwise, decltype(Arr) is TArray<int> and decltype(Brr) is TArray<R>.
//
// But Redcraft can't use the std::from_range_t tag because list-initialization is discouraged.
/** A concept specifies a container that can reserve size. */
template <typename C>
concept CReservableContainer = CSizedRange<C>
&& requires (C& Container, size_t N)
{
Container.Reserve(N);
{ Container.Max() } -> CSameAs<size_t>;
};
/** A concept specifies a container that can append elements. */
template <typename C, typename Ref>
concept CAppendableContainer =
requires (C& Container, Ref&& Reference)
{
requires
(
requires { Container.EmplaceBack (Forward<Ref>(Reference)); } ||
requires { Container.PushBack (Forward<Ref>(Reference)); } ||
requires { Container.Emplace(Container.End(), Forward<Ref>(Reference)); } ||
requires { Container.Insert (Container.End(), Forward<Ref>(Reference)); }
);
};
NAMESPACE_BEGIN(Range)
/** Constructs a non-view object from the elements of the range. */
template <typename C, CInputRange R, typename... Ts> requires (!CView<C>)
NODISCARD FORCEINLINE constexpr auto To(R&& Range, Ts&&... Args)
{
if constexpr (!CInputRange<C> || CConvertibleTo<TRangeReference<R>, TRangeElement<C>>)
{
if constexpr (CConstructibleFrom<C, R, Ts...>)
{
return C(Forward<R>(Range), Forward<Ts>(Args)...);
}
else if constexpr (CCommonRange<R> && CInputRange<R> && CConstructibleFrom<C, TRangeIterator<R>, TRangeSentinel<R>, Ts...>)
{
return C(Range::Begin(Range), Range::End(Range), Forward<Ts>(Args)...);
}
else if constexpr (CConstructibleFrom<C, Ts...> && CAppendableContainer<C, TRangeReference<R>>)
{
C Result(Forward<Ts>(Args)...);
if constexpr (CSizedRange<R> && CReservableContainer<C>)
{
Result.Reserve(Range::Num(Range));
}
for (TRangeReference<R> Element : Range)
{
if constexpr (requires { Result.EmplaceBack(DeclVal<TRangeReference<R>>()); })
{
Result.EmplaceBack(Forward<TRangeReference<R>>(Element));
}
else if constexpr (requires { Result.PushBack(DeclVal<TRangeReference<R>>()); })
{
Result.PushBack(Forward<TRangeReference<R>>(Element));
}
else if constexpr (requires { Result.Emplace(Result.End(), DeclVal<TRangeReference<R>>()); })
{
Result.Emplace(Result.End(), Forward<TRangeReference<R>>(Element));
}
else /* if constexpr (requires { Result.Insert(Result.End(), DeclVal<TRangeReference<R>>()); }) */
{
Result.Insert(Result.End(), Forward<TRangeReference<R>>(Element));
}
}
return Result;
}
else static_assert(sizeof(R) == -1, "The container type is not constructible from a range");
}
else
{
if constexpr (CInputRange<TRangeReference<C>>)
{
return Range::To<C>(Range::All(Range) | Range::Transform([]<typename T>(T&& Element) { return Range::To<TRangeElement<C>>(Forward<T>(Element)); }), Forward<Args>(Args)...);
}
else static_assert(sizeof(R) == -1, "The container type is not constructible from a range");
}
}
/** Constructs a non-view object from the elements of the range. */
template <template <typename...> typename C, CInputRange R, typename... Ts>
NODISCARD FORCEINLINE constexpr auto To(R&& Range, Ts&&... Args)
{
if constexpr (requires { C(DeclVal<R>(), DeclVal<Ts>()...); })
{
return Range::To<decltype(C(DeclVal<R>(), DeclVal<Ts>()...))>(Forward<R>(Range), Forward<Ts>(Args)...);
}
else if constexpr (requires { C(DeclVal<TRangeIterator<R>>(), DeclVal<TRangeSentinel<R>>(), DeclVal<Args>()...); })
{
return Range::To<decltype(C(DeclVal<TRangeIterator<R>>(), DeclVal<TRangeSentinel<R>>(), DeclVal<Args>()...))>(Forward<R>(Range), Forward<Ts>(Args)...);
}
else static_assert(sizeof(R) == -1, "The container type is not constructible from a range");
}
/** Constructs a non-view object from the elements of the range. */
template <typename C, typename... Ts> requires (!CView<C>)
NODISCARD FORCEINLINE constexpr auto To(Ts&&... Args)
{
using FClosure = decltype([]<CInputRange R, typename... Us> requires (requires { Range::To<C>(DeclVal<R>(), DeclVal<Us>()...); }) (R&& Range, Us&&... Args)
{
return Range::To<C>(Forward<R>(Range), Forward<Us>(Args)...);
});
return TAdaptorClosure<FClosure, TDecay<Ts>...>(Forward<Ts>(Args)...);
}
/** Constructs a non-view object from the elements of the range. */
template <template <typename...> typename C, typename... Ts>
NODISCARD FORCEINLINE constexpr auto To(Ts&&... Args)
{
using FClosure = decltype([]<CInputRange R, typename... Us> requires (requires { Range::To<C>(DeclVal<R>(), DeclVal<Us>()...); }) (R&& Range, Us&&... Args)
{
return Range::To<C>(Forward<R>(Range), Forward<Us>(Args)...);
});
return TAdaptorClosure<FClosure, TDecay<Ts>...>(Forward<Ts>(Args)...);
}
NAMESPACE_END(Range)
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -7,6 +7,7 @@
#include "Range/AllView.h" #include "Range/AllView.h"
#include "Memory/Address.h" #include "Memory/Address.h"
#include "Templates/Invoke.h" #include "Templates/Invoke.h"
#include "Iterator/Iterator.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
@ -79,7 +80,7 @@ private:
public: public:
using FElementType = TIteratorElementType<TRangeIterator<V>>; using FElementType = TIteratorElement<TRangeIterator<V>>;
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<V>>) { } // Use '{ }' instead of '= default;' to avoid MSVC bug. FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<V>>) { } // Use '{ }' instead of '= default;' to avoid MSVC bug.
@ -175,10 +176,12 @@ NODISCARD FORCEINLINE constexpr auto Filter(R&& Base, Pred&& Predicate)
template <typename Pred> template <typename Pred>
NODISCARD FORCEINLINE constexpr auto Filter(Pred&& Predicate) NODISCARD FORCEINLINE constexpr auto Filter(Pred&& Predicate)
{ {
return TAdaptorClosure([&Predicate]<CViewableRange R> requires (requires { Range::Filter(DeclVal<R>(), DeclVal<Pred>()); }) (R&& Base) using FClosure = decltype([]<CViewableRange R, typename T> requires (requires { Range::Filter(DeclVal<R>(), DeclVal<T>()); }) (R&& Base, T&& Predicate)
{ {
return Range::Filter(Forward<R>(Base), Forward<Pred>(Predicate)); return Range::Filter(Forward<R>(Base), Forward<T>(Predicate));
}); });
return TAdaptorClosure<FClosure, TDecay<Pred>>(Forward<Pred>(Predicate));
} }
NAMESPACE_END(Range) NAMESPACE_END(Range)

View File

@ -2,6 +2,7 @@
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Utility.h" #include "Range/Utility.h"
#include "Templates/Tuple.h"
#include "Templates/Invoke.h" #include "Templates/Invoke.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
@ -23,50 +24,74 @@ template <CObject D> requires (CSameAs<D, TRemoveCV<D>>)
class IAdaptorClosure { }; class IAdaptorClosure { };
/** An adaptor closure helper that wraps a callable object. */ /** An adaptor closure helper that wraps a callable object. */
template <CMoveConstructible F> template <CDefaultConstructible F, CMoveConstructible... Ts> requires (CEmpty<F> && ... && CSameAs<TDecay<Ts>, Ts>)
class TAdaptorClosure : public IAdaptorClosure<TAdaptorClosure<F>> class TAdaptorClosure : public IAdaptorClosure<TAdaptorClosure<F, Ts...>>
{ {
public: public:
FORCEINLINE constexpr explicit TAdaptorClosure(F InClosure) : Closure(MoveTemp(InClosure)) { } template <typename... Us> requires (CConstructibleFrom<TTuple<Ts...>, Us...> && ... && CSameAs<TDecay<Us>, Ts>)
FORCEINLINE constexpr explicit TAdaptorClosure(Us&&... InArgs) : Args(Forward<Us>(InArgs)...) { }
template <typename R> requires (CInvocable<F&, R>) template <typename R> requires (CInvocable<F, R, Ts&...>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) & NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) &
{ {
return Invoke(Closure, Forward<R>(Range)); return [this, &Range]<size_t... Indices>(TIndexSequence<Indices...>)
{
return Invoke(F(), Forward<R>(Range), Args.template GetValue<Indices>()...);
}
(TMakeIndexSequence<sizeof...(Ts)>());
} }
template <typename R> requires (CInvocable<const F&, R>) template <typename R> requires (CInvocable<F, R, const Ts&...>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const& NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&
{ {
return Invoke(Closure, Forward<R>(Range)); return [this, &Range]<size_t... Indices>(TIndexSequence<Indices...>)
{
return Invoke(F(), Forward<R>(Range), Args.template GetValue<Indices>()...);
}
(TMakeIndexSequence<sizeof...(Ts)>());
} }
template <typename R> requires (CInvocable<F&&, R>) template <typename R> requires (CInvocable<F, R, Ts&&...>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) && NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) &&
{ {
return Invoke(MoveTemp(Closure), Forward<R>(Range)); return [this, &Range]<size_t... Indices>(TIndexSequence<Indices...>)
{
return Invoke(F(), Forward<R>(Range), MoveTemp(Args).template GetValue<Indices>()...);
}
(TMakeIndexSequence<sizeof...(Ts)>());
} }
template <typename R> requires (CInvocable<const F&&, R>) template <typename R> requires (CInvocable<F, R, const Ts&&...>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&& NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&&
{ {
return Invoke(MoveTemp(Closure), Forward<R>(Range)); return [this, &Range]<size_t... Indices>(TIndexSequence<Indices...>)
{
return Invoke(F(), Forward<R>(Range), MoveTemp(Args).template GetValue<Indices>()...);
}
(TMakeIndexSequence<sizeof...(Ts)>());
} }
private: private:
NO_UNIQUE_ADDRESS F Closure; NO_UNIQUE_ADDRESS TTuple<Ts...> Args;
}; };
/** A pipe closure that wraps two adaptor closures. */ /** A pipe closure that wraps two adaptor closures. */
template <CMoveConstructible T, CMoveConstructible U> requires (CDerivedFrom<T, IAdaptorClosure<T>> && CDerivedFrom<U, IAdaptorClosure<U>>) template <CMoveConstructible T, CMoveConstructible U>
requires (CSameAs<TRemoveCVRef<T>, T> && CDerivedFrom<T, IAdaptorClosure<T>>
&& CSameAs<TRemoveCVRef<U>, U> && CDerivedFrom<U, IAdaptorClosure<U>>)
class TPipeClosure final : public IAdaptorClosure<TPipeClosure<T, U>> class TPipeClosure final : public IAdaptorClosure<TPipeClosure<T, U>>
{ {
public: public:
FORCEINLINE constexpr explicit TPipeClosure(T InLHS, U InRHS) : LHS(MoveTemp(InLHS)), RHS(MoveTemp(InRHS)) { } template <typename V, typename W>
requires (CSameAs<TRemoveCVRef<V>, T> && CConstructibleFrom<T, V>
&& CSameAs<TRemoveCVRef<W>, U> && CConstructibleFrom<U, W>)
FORCEINLINE constexpr explicit TPipeClosure(V InLHS, W InRHS)
: LHS(Forward<V>(InLHS)), RHS(Forward<W>(InRHS))
{ }
template <typename R> requires (CInvocable<T&, R> && CInvocable<U&, TInvokeResult<T&, R>>) template <typename R> requires (CInvocable<T&, R> && CInvocable<U&, TInvokeResult<T&, R>>)
NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) & NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) &
@ -106,10 +131,12 @@ NODISCARD FORCEINLINE constexpr auto operator|(R&& Range, T&& Closure)
} }
/** Create a pipe closure that wraps two adaptor closures. */ /** Create a pipe closure that wraps two adaptor closures. */
template <CMoveConstructible T, CMoveConstructible U> requires (CDerivedFrom<T, IAdaptorClosure<T>> && CDerivedFrom<U, IAdaptorClosure<U>>) template <CMoveConstructible T, CMoveConstructible U>
NODISCARD FORCEINLINE constexpr auto operator|(T LHS, U RHS) requires (CDerivedFrom<TRemoveCVRef<T>, IAdaptorClosure<TRemoveCVRef<T>>>
&& CDerivedFrom<TRemoveCVRef<U>, IAdaptorClosure<TRemoveCVRef<U>>>)
NODISCARD FORCEINLINE constexpr auto operator|(T&& LHS, U&& RHS)
{ {
return TPipeClosure(MoveTemp(LHS), MoveTemp(RHS)); return TPipeClosure<TRemoveCVRef<T>, TRemoveCVRef<U>>(Forward<T>(LHS), Forward<U>(RHS));
} }
NAMESPACE_END(Range) NAMESPACE_END(Range)

View File

@ -3,6 +3,7 @@
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Utility.h" #include "Range/Utility.h"
#include "Range/View.h" #include "Range/View.h"
#include "Range/Conversion.h"
#include "Range/Factory.h" #include "Range/Factory.h"
#include "Range/Pipe.h" #include "Range/Pipe.h"
#include "Range/AllView.h" #include "Range/AllView.h"

View File

@ -222,10 +222,12 @@ NODISCARD FORCEINLINE constexpr auto Transform(R&& Base, F&& Func)
template <typename F> template <typename F>
NODISCARD FORCEINLINE constexpr auto Transform(F&& Func) NODISCARD FORCEINLINE constexpr auto Transform(F&& Func)
{ {
return TAdaptorClosure([&Func]<CViewableRange R> requires (requires { Range::Transform(DeclVal<R>(), DeclVal<F>()); }) (R&& Base) using FClosure = decltype([]<CViewableRange R, typename T> requires (requires { Range::Transform(DeclVal<R>(), DeclVal<T>()); }) (R&& Base, T&& Func)
{ {
return Range::Transform(Forward<R>(Base), Forward<F>(Func)); return Range::Transform(Forward<R>(Base), Forward<T>(Func));
}); });
return TAdaptorClosure<FClosure, TDecay<F>>(Forward<F>(Func));
} }
NAMESPACE_END(Range) NAMESPACE_END(Range)

View File

@ -37,7 +37,7 @@ NODISCARD FORCEINLINE constexpr auto Begin(T&& Container)
/** Overloads the Begin algorithm for initializer_list. */ /** Overloads the Begin algorithm for initializer_list. */
template <typename T> template <typename T>
NODISCARD FORCEINLINE constexpr auto Begin(initializer_list<T>& Container) NODISCARD FORCEINLINE constexpr const T* Begin(initializer_list<T>& Container)
{ {
return Container.begin(); return Container.begin();
} }
@ -67,7 +67,7 @@ NODISCARD FORCEINLINE constexpr auto End(T&& Container)
/** Overloads the End algorithm for initializer_list. */ /** Overloads the End algorithm for initializer_list. */
template <typename T> template <typename T>
NODISCARD FORCEINLINE constexpr auto End(initializer_list<T>& Container) NODISCARD FORCEINLINE constexpr const T* End(initializer_list<T>& Container)
{ {
return Container.end(); return Container.end();
} }
@ -180,6 +180,13 @@ NODISCARD FORCEINLINE constexpr size_t Num(T&& Container)
return Range::End(Forward<T>(Container)) - Range::Begin(Forward<T>(Container)); return Range::End(Forward<T>(Container)) - Range::Begin(Forward<T>(Container));
} }
/** Overloads the Num algorithm for initializer_list. */
template <typename T>
NODISCARD FORCEINLINE constexpr size_t Num(initializer_list<T>& Container)
{
return Container.size();
}
/** @return true if the container is empty, false otherwise. */ /** @return true if the container is empty, false otherwise. */
template <typename T> requires (requires(T&& Container) { { Container.IsEmpty() } -> CBooleanTestable; }) template <typename T> requires (requires(T&& Container) { { Container.IsEmpty() } -> CBooleanTestable; })
NODISCARD FORCEINLINE constexpr bool IsEmpty(T&& Container) NODISCARD FORCEINLINE constexpr bool IsEmpty(T&& Container)

View File

@ -2,6 +2,7 @@
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Utility.h" #include "Range/Utility.h"
#include "Iterator/Iterator.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
@ -100,7 +101,7 @@ class TRangeView : public IBasicViewInterface<TRangeView<I, S>>
{ {
public: public:
using FElementType = TIteratorElementType<I>; using FElementType = TIteratorElement<I>;
FORCEINLINE constexpr TRangeView() requires (CDefaultConstructible<I>) = default; FORCEINLINE constexpr TRangeView() requires (CDefaultConstructible<I>) = default;

View File

@ -900,7 +900,7 @@ struct TStringObjectFormatter
} }
// Format the container value by format string. // Format the container value by format string.
else if constexpr (requires { Iteration::Begin(Object); Iteration::End(Object); }) else if constexpr (requires { Range::Begin(Object); Range::End(Object); })
{ {
auto FillAndAlign = ParseFillAndAlign(); auto FillAndAlign = ParseFillAndAlign();
@ -951,7 +951,7 @@ struct TStringObjectFormatter
return false; return false;
} }
if (Iteration::Begin(Object) == Iteration::End(Object)) if (Range::Begin(Object) == Range::End(Object))
{ {
Result += Begin; Result += Begin;
Result += End; Result += End;
@ -966,7 +966,7 @@ struct TStringObjectFormatter
struct { TStringView<T> Fmt; } ElementParam = { Subfmt }; struct { TStringView<T> Fmt; } ElementParam = { Subfmt };
// It is assumed that if the first element is successfully formatted, all elements will succeed. // It is assumed that if the first element is successfully formatted, all elements will succeed.
bool bIsSuccessful = TStringObjectFormatter::Do(Buffer, *Iteration::Begin(Object), ElementParam); bool bIsSuccessful = TStringObjectFormatter::Do(Buffer, *Range::Begin(Object), ElementParam);
if (!bIsSuccessful) if (!bIsSuccessful)
{ {
@ -977,9 +977,9 @@ struct TStringObjectFormatter
Result += Begin; Result += Begin;
Result += Buffer; Result += Buffer;
auto Sentinel = Iteration::End(Object); auto Sentinel = Range::End(Object);
for (auto Iter = ++Iteration::Begin(Object); Iter != Sentinel; ++Iter) for (auto Iter = ++Range::Begin(Object); Iter != Sentinel; ++Iter)
{ {
Result += Separator; Result += Separator;

View File

@ -1,15 +1,15 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Range.h"
#include "String/Char.h" #include "String/Char.h"
#include "Containers/Array.h" #include "Containers/Array.h"
#include "String/StringView.h" #include "String/StringView.h"
#include "Iterator/Iterator.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "Templates/Optional.h" #include "Templates/Optional.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
#include "Templates/Noncopyable.h" #include "Templates/Noncopyable.h"
#include "Miscellaneous/Iterator.h"
#include "Miscellaneous/Container.h"
#include "Miscellaneous/AssertionMacros.h" #include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN NAMESPACE_REDCRAFT_BEGIN
@ -80,9 +80,14 @@ public:
FORCEINLINE TString(TStringView<FElementType> 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<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReference<I>>)
FORCEINLINE TString(I First, S Last) : FSuper(MoveTemp(First), MoveTemp(Last)) { } FORCEINLINE TString(I First, S Last) : FSuper(MoveTemp(First), MoveTemp(Last)) { }
/** Constructs the string with the contents of the range. */
template <CInputRange R> requires (!CSameAs<TRemoveCVRef<R>, TString>
&& !CSameAs<TRemoveCVRef<R>, TStringView<FElementType>> && CConstructibleFrom<FElementType, TRangeReference<R>>)
FORCEINLINE explicit TString(R&& Range) : TString(Range::Begin(Range), Range::End(Range)) { }
/** 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 +95,7 @@ public:
FORCEINLINE TString(TString&&) = default; FORCEINLINE TString(TString&&) = default;
/** Constructs the string with the contents of the initializer list. */ /** Constructs the string with the contents of the initializer list. */
FORCEINLINE TString(initializer_list<FElementType> IL) : TString(Iteration::Begin(IL), Iteration::End(IL)) { } FORCEINLINE TString(initializer_list<FElementType> IL) : TString(Range::Begin(IL), Range::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;
@ -167,7 +172,7 @@ public:
} }
/** Inserts characters from the range ['First', 'Last') before 'Index' in the string. */ /** Inserts characters from the range ['First', 'Last') before 'Index' in the string. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReference<I>>)
FORCEINLINE FIterator 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,7 +181,7 @@ public:
} }
/** Inserts characters from the range ['First', 'Last') before 'Iter'. */ /** Inserts characters from the range ['First', 'Last') before 'Iter'. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReference<I>>)
FORCEINLINE FIterator Insert(FConstIterator 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()."));
@ -237,20 +242,33 @@ public:
void StableErase(...) = delete; void StableErase(...) = delete;
/** Appends 'Count' copies of the 'InValue' to the end of the string. */ /** Appends 'Count' copies of the 'InValue' to the end of the string. */
TString& Append(size_t Count, FElementType InChar) { return Append(MakeCountedConstantIterator(InChar, Count), DefaultSentinel); } TString& Append(size_t Count, FElementType InChar) { return Append(Range::Repeat(InChar, Count)); }
/** Appends the contents of the 'View' to the end of the string. */ /** Appends the contents of the range ['InPtr', 'InPtr' + 'Count') to the end of the string. */
FORCEINLINE TString& Append(TStringView<FElementType> View) { return Append(View.Begin(), View.End()); } FORCEINLINE TString& Append(const FElementType* InPtr, size_t Count) { return Append(TStringView<FElementType>(InPtr, Count)); }
FORCEINLINE TString& Append(nullptr_t, size_t) = delete;
/** Constructs a string with the contents of the range ['InPtr', '\0'). */
FORCEINLINE TString& Append(const FElementType* InPtr) { return Append(TStringView<FElementType>(InPtr)); }
FORCEINLINE TString& Append(nullptr_t) = delete;
/** Appends the contents of the range ['First', 'Last') to the end of the string. */ /** Appends the contents of the range ['First', 'Last') to the end of the string. */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReference<I>>)
TString& Append(I First, S Last) TString& Append(I First, S Last)
{ {
if constexpr (CForwardIterator<I>) if constexpr (CForwardIterator<I>)
{ {
if constexpr (CSizedSentinelFor<S, I>) { checkf(First <= Last, TEXT("Illegal range iterator. Please check First <= Last.")); } size_t Count = 0;
const size_t Count = Iteration::Distance(First, Last); if constexpr (CSizedSentinelFor<S, I>)
{
checkf(First - Last <= 0, TEXT("Illegal range iterator. Please check First <= Last."));
Count = Last - First;
}
else for (I Iter = First; Iter != Last; ++Iter) ++Count;
const size_t CurrentNum = this->Num(); const size_t CurrentNum = this->Num();
@ -269,14 +287,24 @@ public:
return *this; return *this;
} }
/** Appends the contents of the range to the end of the string. */
template <CInputRange R> requires (CConstructibleFrom<FElementType, TRangeReference<R>>)
FORCEINLINE TString& Append(R&& Range) { return Append(Range::Begin(Range), Range::End(Range)); }
/** Appends the contents of the initializer list to the end of the string. */ /** Appends the contents of the initializer list to the end of the string. */
FORCEINLINE TString& Append(initializer_list<FElementType> IL) { return Append(Iteration::Begin(IL), Iteration::End(IL)); } FORCEINLINE TString& Append(initializer_list<FElementType> IL) { return Append(Range::Begin(IL), Range::End(IL)); }
/** Appends the given character value to the end of the string. */ /** Appends the given character value to the end of the string. */
FORCEINLINE TString& operator+=(FElementType InChar) { return Append(1, InChar); } FORCEINLINE TString& operator+=(FElementType InChar) { return Append(1, InChar); }
/** Appends the contents of the 'View' to the end of the string. */ /** Appends the contents of the range ['InPtr', '\0') to the end of the string. */
FORCEINLINE TString& operator+=(TStringView<FElementType> View) { return Append(View); } FORCEINLINE TString& operator+=(const FElementType* InPtr) { return Append(InPtr); }
FORCEINLINE TString& operator+=(nullptr_t) = delete;
/** Appends the contents of the range to the end of the string. */
template <CInputRange R> requires (CConstructibleFrom<FElementType, TRangeReference<R>>)
FORCEINLINE TString& operator+=(R&& Range) { return Append(Range); }
/** Appends the contents of the range ['First', 'Last') to the end of the string. */ /** Appends the contents of the range ['First', 'Last') to the end of the string. */
FORCEINLINE TString& operator+=(initializer_list<FElementType> IL) { return Append(IL); } FORCEINLINE TString& operator+=(initializer_list<FElementType> IL) { return Append(IL); }
@ -435,27 +463,49 @@ public:
{ {
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 Replace(First, Last, MakeCountedConstantIterator(InChar, Count), DefaultSentinel); return Replace(First, Last, Range::Repeat(InChar, Count));
} }
/** Replace the substring [Index, Index + CountToReplace) with the contents of the 'View'. */ /** Replace the substring [Index, Index + CountToReplace) with the contents of the ['InPtr', 'InPtr' + 'Count'). */
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, TStringView<FElementType> View) FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, const FElementType* InPtr, size_t Count)
{ {
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."));
return Replace(this->Begin() + Index, this->Begin() + Index + CountToReplace, View); return Replace(this->Begin() + Index, this->Begin() + Index + CountToReplace, InPtr, InPtr + Count);
} }
/** Replace the substring ['First', 'Last') with the contents of the 'View'. */ FORCEINLINE TString& Replace(size_t, size_t, nullptr_t, size_t) = delete;
FORCEINLINE TString& Replace(FConstIterator First, FConstIterator Last, TStringView<FElementType> View)
/** Replace the substring ['First', 'Last') with the contents of the ['InPtr', 'InPtr' + 'Count'). */
FORCEINLINE TString& Replace(FConstIterator First, FConstIterator Last, const FElementType* InPtr, size_t Count)
{ {
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 Replace(First, Last, View.Begin(), View.End()); return Replace(First, Last, TStringView<FElementType>(InPtr, Count));
}
FORCEINLINE TString& Replace(FConstIterator, FConstIterator, nullptr_t, size_t) = delete;
/** Replace the substring [Index, Index + CountToReplace) with the contents of the ['InPtr', '\0'). */
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, const FElementType* InPtr)
{
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
return Replace(this->Begin() + Index, this->Begin() + Index + CountToReplace, InPtr);
}
FORCEINLINE TString& Replace(size_t, size_t, nullptr_t) = delete;
/** Replace the substring ['First', 'Last') with the contents of the ['InPtr', '\0'). */
FORCEINLINE TString& Replace(FConstIterator First, FConstIterator Last, const FElementType* InPtr)
{
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
return Replace(First, Last, TStringView<FElementType>(InPtr));
} }
/** Replace the substring [Index, Index + CountToReplace) with the contents of the range ['First', 'Last'). */ /** Replace the substring [Index, Index + CountToReplace) with the contents of the range ['First', 'Last'). */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReference<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,19 +514,27 @@ public:
} }
/** Replace the substring ['First', 'Last') with the contents of the range ['InString', 'Sentinel'). */ /** Replace the substring ['First', 'Last') with the contents of the range ['InString', 'Sentinel'). */
template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReferenceType<I>>) template <CInputIterator I, CSentinelFor<I> S> requires (CConstructibleFrom<FElementType, TIteratorReference<I>>)
TString& Replace(FConstIterator First, FConstIterator 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()."));
if constexpr (CForwardIterator<I>) if constexpr (CForwardIterator<I>)
{ {
if constexpr (CSizedSentinelFor<S, I>) { checkf(First - Last <= 0, TEXT("Illegal range iterator. Please check First <= Last.")); } checkf(First - Last <= 0, TEXT("Illegal range iterator. Please check First <= Last."));
const size_t InsertIndex = First - this->Begin(); const size_t InsertIndex = First - this->Begin();
const size_t RemoveCount = Last - First;
const size_t RemoveCount = Iteration::Distance(First, Last); size_t InsertCount = 0;
const size_t InsertCount = Iteration::Distance(InString, Sentinel);
if constexpr (CSizedSentinelFor<S, I>)
{
checkf(InString - Sentinel <= 0, TEXT("Illegal range iterator. Please check InString <= Sentinel."));
InsertCount = Sentinel - InString;
}
else for (I Iter = InString; Iter != Sentinel; ++Iter) ++InsertCount;
const size_t NumToReset = this->Num() - RemoveCount + InsertCount; const size_t NumToReset = this->Num() - RemoveCount + InsertCount;
@ -519,6 +577,24 @@ public:
return *this; return *this;
} }
/** Replace the substring [Index, Index + CountToReplace) with the contents of the range. */
template <CInputRange R> requires (CConstructibleFrom<FElementType, TRangeReference<R>>)
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, R&& Range)
{
checkf(Index <= this->Num() && Index + CountToReplace <= this->Num(), TEXT("Illegal substring range. Please check Index and CountToReplace."));
return Replace(this->Begin() + Index, this->Begin() + Index + CountToReplace, Forward<R>(Range));
}
/** Replace the substring ['First', 'Last') with the contents of the range. */
template <CInputRange R> requires (CConstructibleFrom<FElementType, TRangeReference<R>>)
FORCEINLINE TString& Replace(FConstIterator First, FConstIterator Last, R&& Range)
{
checkf(this->IsValidIterator(First) && this->IsValidIterator(Last) && First <= Last, TEXT("Read access violation. Please check IsValidIterator()."));
return Replace(First, Last, Range::Begin(Range), Range::End(Range));
}
/** Replace the substring [Index, Index + CountToReplace) with the contents of the initializer list. */ /** Replace the substring [Index, Index + CountToReplace) with the contents of the initializer list. */
FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, initializer_list<FElementType> IL) FORCEINLINE TString& Replace(size_t Index, size_t CountToReplace, initializer_list<FElementType> IL)
{ {
@ -532,7 +608,7 @@ public:
{ {
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 Replace(First, Last, Iteration::Begin(IL), Iteration::End(IL)); return Replace(First, Last, Range::Begin(IL), Range::End(IL));
} }
/** Obtains a string that is a view over the 'Count' characters of this string view starting at 'Offset'. */ /** Obtains a string that is a view over the 'Count' characters of this string view starting at 'Offset'. */
@ -540,7 +616,7 @@ public:
{ {
checkf(Offset <= this->Num() && Offset + Count <= this->Num(), TEXT("Illegal substring range. Please check Offset and Count.")); checkf(Offset <= this->Num() && Offset + Count <= this->Num(), TEXT("Illegal substring range. Please check Offset and Count."));
return TStringView<FElementType>(*this).Substr(Offset, Count); return TString(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. */
@ -725,7 +801,7 @@ public:
do do
{ {
const auto Result = Facet.in(State, BeginFrom, EndFrom, NextFrom, Iteration::Begin(Buffer), Iteration::End(Buffer), NextTo); const auto Result = Facet.in(State, BeginFrom, EndFrom, NextFrom, Range::Begin(Buffer), Range::End(Buffer), NextTo);
if (BeginFrom == NextFrom) return false; if (BeginFrom == NextFrom) return false;
@ -773,7 +849,7 @@ public:
do do
{ {
const auto Result = Facet.out(State, BeginFrom, EndFrom, NextFrom, Iteration::Begin(Buffer), Iteration::End(Buffer), NextTo); const auto Result = Facet.out(State, BeginFrom, EndFrom, NextFrom, Range::Begin(Buffer), Range::End(Buffer), NextTo);
if (BeginFrom == NextFrom) return false; if (BeginFrom == NextFrom) return false;
@ -1360,8 +1436,11 @@ TString(const T*) -> TString<T>;
template<typename T> template<typename T>
TString(TStringView<T>) -> TString<T>; TString(TStringView<T>) -> TString<T>;
template<CForwardIterator I, typename S> template<typename I, typename S>
TString(I, S) -> TString<TIteratorElementType<I>>; TString(I, S) -> TString<TIteratorElement<I>>;
template<typename R>
TString(R) -> TString<TRangeElement<R>>;
template <typename T> template <typename T>
TString(initializer_list<T>) -> TString<T>; TString(initializer_list<T>) -> TString<T>;

View File

@ -1,17 +1,16 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Range.h"
#include "String/Char.h" #include "String/Char.h"
#include "Memory/Allocator.h" #include "Memory/Allocator.h"
#include "Iterator/Iterator.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "Templates/TypeHash.h" #include "Templates/TypeHash.h"
#include "Containers/ArrayView.h" #include "Containers/ArrayView.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
#include "Memory/MemoryOperator.h" #include "Memory/MemoryOperator.h"
#include "Miscellaneous/Iterator.h"
#include "Miscellaneous/Container.h"
#include "Miscellaneous/AssertionMacros.h" #include "Miscellaneous/AssertionMacros.h"
#include "Miscellaneous/ConstantIterator.h"
#include <cstring> #include <cstring>
#include <cwchar> #include <cwchar>
@ -86,7 +85,7 @@ private:
public: public:
using FElementType = T; using FElementType = TRemoveCV<T>;
using FReference = typename FSuper::FReference; using FReference = typename FSuper::FReference;
@ -99,11 +98,11 @@ public:
FORCEINLINE constexpr TStringView() = default; FORCEINLINE constexpr TStringView() = default;
/** Constructs a string view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */ /** Constructs a string view that is a view over the range ['InFirst', 'InFirst' + 'Count'). */
template <CContiguousIterator I> requires (CConvertibleTo<TIteratorElementType<I>(*)[], const FElementType(*)[]>) template <CContiguousIterator I> requires (CConvertibleTo<TIteratorReference<I>, T> && CSameAs<TRemoveCVRef<TIteratorReference<I>>, TRemoveCVRef<T>>)
FORCEINLINE constexpr TStringView(I InFirst, size_t InCount) : FSuper(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 FElementType(*)[]>) template <CContiguousIterator I, CSizedSentinelFor<I> S> requires (CConvertibleTo<TIteratorReference<I>, T> && CSameAs<TRemoveCVRef<TIteratorReference<I>>, TRemoveCVRef<T>>)
FORCEINLINE constexpr TStringView(I InFirst, S InLast) : FSuper(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'. */
@ -663,8 +662,11 @@ public:
}; };
template <CPointer I>
TStringView(I) -> TStringView<TIteratorElement<I>>;
template <typename I, typename S> template <typename I, typename S>
TStringView(I, S) -> TStringView<TIteratorElementType<I>>; TStringView(I, S) -> TStringView<TIteratorElement<I>>;
template<typename T, typename Allocator> template<typename T, typename Allocator>
TStringView(TString<T, Allocator>) -> TStringView<T>; TStringView(TString<T, Allocator>) -> TStringView<T>;

View File

@ -3,7 +3,6 @@
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
#include "Miscellaneous/Container.h"
NAMESPACE_REDCRAFT_BEGIN NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Redcraft)
@ -13,8 +12,7 @@ template <typename T, T... Ints>
struct TIntegerSequence struct TIntegerSequence
{ {
using FValueType = 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... }); }
}; };
NAMESPACE_PRIVATE_BEGIN NAMESPACE_PRIVATE_BEGIN

View File

@ -56,8 +56,8 @@ public:
FORCEINLINE constexpr TOptional(FInvalid) : TOptional() { } FORCEINLINE constexpr TOptional(FInvalid) : TOptional() { }
/** Constructs an object with initial content an object, direct-initialized from Forward<U>(InValue). */ /** Constructs an object with initial content an object, direct-initialized from Forward<U>(InValue). */
template <typename U = T> requires (CConstructibleFrom<T, U&&>) template <typename U = T> requires (CConstructibleFrom<T, U&&>
&& (!CSameAs<TRemoveCVRef<U>, FInPlace>) && (!CSameAs<TOptional, TRemoveCVRef<U>>) && !CSameAs<TRemoveCVRef<U>, FInPlace> && !CSameAs<TOptional, TRemoveCVRef<U>>)
FORCEINLINE constexpr explicit (!CConvertibleTo<U&&, T>) TOptional(U&& InValue) FORCEINLINE constexpr explicit (!CConvertibleTo<U&&, T>) TOptional(U&& InValue)
: TOptional(InPlace, Forward<U>(InValue)) : TOptional(InPlace, Forward<U>(InValue))
{ } { }

View File

@ -94,6 +94,20 @@ FORCEINLINE constexpr size_t GetTypeHash(const T& A)
return GetTypeHash(A.hash_code()); return GetTypeHash(A.hash_code());
} }
/** Overloads the GetTypeHash algorithm for arrays. */
template <typename T, size_t N> requires (requires(const T& A) { { GetTypeHash(A) } -> CSameAs<size_t>; })
FORCEINLINE constexpr size_t GetTypeHash(T(&A)[N])
{
size_t Result = 3516520171;
for (size_t Index = 0; Index < N; ++Index)
{
Result = HashCombine(Result, GetTypeHash(A[Index]));
}
return Result;
}
template <typename T> template <typename T>
concept CHashable = requires(const T& A) { { GetTypeHash(A) } -> CSameAs<size_t>; }; concept CHashable = requires(const T& A) { { GetTypeHash(A) } -> CSameAs<size_t>; };

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "TypeTraits/CompositeType.h"
#include "TypeTraits/Miscellaneous.h" #include "TypeTraits/Miscellaneous.h"
#include "TypeTraits/SupportedOperations.h" #include "TypeTraits/SupportedOperations.h"
@ -73,6 +72,16 @@ FORCEINLINE constexpr void Swap(T& A, T& B)
B = MoveTemp(Temp); B = MoveTemp(Temp);
} }
/** Overloads the Swap algorithm for arrays. */
template <typename T, size_t N> requires (requires(T& A, T& B) { Swap(A, B); })
FORCEINLINE constexpr void Swap(T(&A)[N], T(&B)[N])
{
for (size_t Index = 0; Index != N; ++Index)
{
Swap(A[Index], B[Index]);
}
}
/** Replaces the value of 'A' with 'B' and returns the old value of 'A'. */ /** Replaces the value of 'A' with 'B' and returns the old value of 'A'. */
template <typename T, typename U = T> requires (CMoveConstructible<T> && CAssignableFrom<T&, U>) template <typename T, typename U = T> requires (CMoveConstructible<T> && CAssignableFrom<T&, U>)
FORCEINLINE constexpr T Exchange(T& A, U&& B) FORCEINLINE constexpr T Exchange(T& A, U&& B)

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Range/Utility.h"
#include "Templates/Meta.h" #include "Templates/Meta.h"
#include "Templates/Invoke.h" #include "Templates/Invoke.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
@ -478,7 +479,7 @@ struct TVariantVisitImpl
for (size_t Index = 0; Index < sizeof...(VariantTypes); ++Index) for (size_t Index = 0; Index < sizeof...(VariantTypes); ++Index)
{ {
Result *= VariantNums[Index]; Result *= VariantNums[Index];
Result += GetData(Indices)[Index]; Result += Range::Begin(Indices)[Index];
} }
return Result; return Result;