refactor(iterator): add iterator example class and split iterator library into multiple files
This commit is contained in:
parent
ea625bb916
commit
24dd4347d1
@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Iterator/Utility.h"
|
||||
#include "Iterator/Sentinel.h"
|
||||
#include "Iterator/ForwardIterator.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
#if PLATFORM_COMPILER_GCC
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wnon-template-friend"
|
||||
#endif
|
||||
|
||||
/** A concept specifies a type is a bidirectional iterator. Add the decrement operator to the forward iterator. */
|
||||
template <typename I>
|
||||
concept CBidirectionalIterator = CForwardIterator<I>
|
||||
&& requires(I Iter) {
|
||||
{ --Iter } -> CSameAs<I&>;
|
||||
{ Iter-- } -> CSameAs<I >;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is an example of a bidirectional iterator, indicate the traits that define a bidirectional iterator.
|
||||
* Regardless of the order in which the increment and decrement operators are applied,
|
||||
* the result is always the same if both operations are performed the same number of times.
|
||||
*/
|
||||
template <CReference T>
|
||||
struct IBidirectionalIterator /* : IForwardIterator<T> */
|
||||
{
|
||||
/** The element type of the indirectly readable type. See 'IIndirectlyReadable'. */
|
||||
using ElementType = TRemoveCVRef<T>;
|
||||
|
||||
/** Default constructor. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IBidirectionalIterator();
|
||||
|
||||
/** Copy constructor. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IBidirectionalIterator(const IBidirectionalIterator&);
|
||||
|
||||
/** Copy assignment operator. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IBidirectionalIterator* operator=(const IBidirectionalIterator&);
|
||||
|
||||
/** Equality operator. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
friend bool operator==(const IBidirectionalIterator&, const IBidirectionalIterator&);
|
||||
|
||||
/** Dereference operator. See 'IForwardIterator'. */
|
||||
T operator*() const;
|
||||
|
||||
/** Pre-increment operator. See 'IWeaklyIncrementable'. */
|
||||
IBidirectionalIterator& operator++();
|
||||
|
||||
/** Pre-decrement operator. */
|
||||
IBidirectionalIterator& operator--();
|
||||
|
||||
/** Post-increment operator. See 'IIncrementable'. */
|
||||
IBidirectionalIterator operator++(int);
|
||||
|
||||
/** Post-decrement operator. */
|
||||
IBidirectionalIterator operator--(int);
|
||||
};
|
||||
|
||||
// Use 'IBidirectionalIterator<int>' represents a bidirectional iterator.
|
||||
static_assert(CBidirectionalIterator<IBidirectionalIterator<int&>>);
|
||||
static_assert( COutputIterator<IBidirectionalIterator<int&>, int>);
|
||||
|
||||
#if PLATFORM_COMPILER_GCC
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
109
Redcraft.Utility/Source/Public/Iterator/ContiguousIterator.h
Normal file
109
Redcraft.Utility/Source/Public/Iterator/ContiguousIterator.h
Normal file
@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Iterator/Utility.h"
|
||||
#include "Iterator/Sentinel.h"
|
||||
#include "Iterator/RandomAccessIterator.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
#if PLATFORM_COMPILER_GCC
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wnon-template-friend"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A concept specifies a type is a contiguous iterator.
|
||||
* Add the 'operator->' to the random access iterator and requires the 'operator*' returns a true reference type.
|
||||
*/
|
||||
template <typename I>
|
||||
concept CContiguousIterator = CRandomAccessIterator<I> && CLValueReference<TIteratorReference<I>>
|
||||
&& CSameAs<TIteratorElement<I>, TRemoveCVRef<TIteratorReference<I>>>
|
||||
&& CSameAs<TIteratorPointer<I>, TAddPointer<TIteratorReference<I>>>
|
||||
&& requires(I& Iter)
|
||||
{
|
||||
{ ToAddress(Iter) } -> CSameAs<TAddPointer<TIteratorReference<I>>>;
|
||||
};
|
||||
|
||||
/** This is an example of a contiguous iterator, indicate the traits that define a contiguous iterator. */
|
||||
template <CLValueReference T>
|
||||
struct IContiguousIterator /* : IBidirectionalIterator<T> */
|
||||
{
|
||||
/** The element type of the indirectly readable type. See 'IIndirectlyReadable'. */
|
||||
using ElementType = TRemoveCVRef<T>;
|
||||
|
||||
/** Default constructor. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IContiguousIterator();
|
||||
|
||||
/** Copy constructor. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IContiguousIterator(const IContiguousIterator&);
|
||||
|
||||
/** Copy assignment operator. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IContiguousIterator* operator=(const IContiguousIterator&);
|
||||
|
||||
/** Equality operator. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
friend bool operator==(const IContiguousIterator&, const IContiguousIterator&);
|
||||
|
||||
/** Three-way comparison operator. See 'IRandomAccessIterator'. */
|
||||
friend strong_ordering operator<=>(const IContiguousIterator& LHS, const IContiguousIterator& RHS);
|
||||
|
||||
/**
|
||||
* Dereference operator. See 'IForwardIterator'.
|
||||
* Specify, the return type must be a true reference type and refer to an element of a contiguous sequence, not a proxy class.
|
||||
*/
|
||||
T operator*() const;
|
||||
|
||||
/** Indirection operator. Return the address of the element that the iterator is pointing to. */
|
||||
TAddPointer<T> operator->() const;
|
||||
|
||||
/** Pre-increment operator. See 'IWeaklyIncrementable'. */
|
||||
IContiguousIterator& operator++();
|
||||
|
||||
/** Pre-decrement operator. See 'IBidirectionalIterator'. */
|
||||
IContiguousIterator& operator--();
|
||||
|
||||
/** Post-increment operator. See 'IIncrementable'. */
|
||||
IContiguousIterator operator++(int);
|
||||
|
||||
/** Post-decrement operator. See 'IBidirectionalIterator'. */
|
||||
IContiguousIterator operator--(int);
|
||||
|
||||
/** Addition assignment operator. See 'IRandomAccessIterator'. */
|
||||
IContiguousIterator& operator+=(ptrdiff);
|
||||
|
||||
/** Subtraction assignment operator. See 'IRandomAccessIterator'. */
|
||||
IContiguousIterator& operator-=(ptrdiff);
|
||||
|
||||
/** Addition operator. See 'IRandomAccessIterator'. */
|
||||
IContiguousIterator operator+(ptrdiff) const;
|
||||
|
||||
/** Subtraction operator. See 'IRandomAccessIterator'. */
|
||||
IContiguousIterator operator-(ptrdiff) const;
|
||||
|
||||
/** Addition operator. See 'IRandomAccessIterator'. */
|
||||
friend IContiguousIterator operator+(ptrdiff, const IContiguousIterator&);
|
||||
|
||||
/** Subtraction operator. See 'IRandomAccessIterator'. */
|
||||
friend ptrdiff operator-(const IContiguousIterator&, const IContiguousIterator&);
|
||||
|
||||
/** Subscript operator. See 'IRandomAccessIterator'. */
|
||||
T operator[](ptrdiff) const;
|
||||
};
|
||||
|
||||
// Use 'IContiguousIterator<int>' represents a contiguous iterator
|
||||
static_assert(CContiguousIterator<IContiguousIterator<int&>>);
|
||||
static_assert( COutputIterator<IContiguousIterator<int&>, int>);
|
||||
|
||||
// The 'int*' is the most typical example of a contiguous iterator
|
||||
static_assert(CContiguousIterator<int*>);
|
||||
|
||||
#if PLATFORM_COMPILER_GCC
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
63
Redcraft.Utility/Source/Public/Iterator/ForwardIterator.h
Normal file
63
Redcraft.Utility/Source/Public/Iterator/ForwardIterator.h
Normal file
@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Iterator/Utility.h"
|
||||
#include "Iterator/Sentinel.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
#if PLATFORM_COMPILER_GCC
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wnon-template-friend"
|
||||
#endif
|
||||
|
||||
/** A concept specifies a type is an input iterator. It is input iterator, incrementable, and sentinel for itself. */
|
||||
template <typename I>
|
||||
concept CForwardIterator = CInputIterator<I> && CIncrementable<I> && CSentinelFor<I, I>;
|
||||
|
||||
/** This is an example of a forward iterator, indicate the traits that define a forward iterator. */
|
||||
template <CReference T>
|
||||
struct IForwardIterator /* : IInputIterator<T>, IIncrementable, ISentinelFor<I> */
|
||||
{
|
||||
/** The element type of the indirectly readable type. See 'IIndirectlyReadable'. */
|
||||
using ElementType = TRemoveCVRef<T>;
|
||||
|
||||
/** Default constructor. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IForwardIterator();
|
||||
|
||||
/** Copy constructor. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IForwardIterator(const IForwardIterator&);
|
||||
|
||||
/** Copy assignment operator. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IForwardIterator* operator=(const IForwardIterator&);
|
||||
|
||||
/** Equality operator. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
friend bool operator==(const IForwardIterator&, const IForwardIterator&);
|
||||
|
||||
/**
|
||||
* Indirectly read the element from the indirectly readable type. See 'IIndirectlyReadable'.
|
||||
* Indirectly write the element if the type is also an indirectly writable type. See 'IIndirectlyWritable'.
|
||||
*/
|
||||
T operator*() const;
|
||||
|
||||
/** Pre-increment operator. See 'IWeaklyIncrementable'. */
|
||||
IForwardIterator& operator++();
|
||||
|
||||
/** Post-increment operator. See 'IIncrementable'. */
|
||||
IForwardIterator operator++(int);
|
||||
};
|
||||
|
||||
// Use 'IForwardIterator<int>' represents a forward iterator.
|
||||
static_assert(CForwardIterator<IForwardIterator<int&>>);
|
||||
static_assert( COutputIterator<IForwardIterator<int&>, int>);
|
||||
|
||||
#if PLATFORM_COMPILER_GCC
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
9
Redcraft.Utility/Source/Public/Iterator/Iterator.h
Normal file
9
Redcraft.Utility/Source/Public/Iterator/Iterator.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Iterator/Utility.h"
|
||||
#include "Iterator/Sentinel.h"
|
||||
#include "Iterator/ForwardIterator.h"
|
||||
#include "Iterator/BidirectionalIterator.h"
|
||||
#include "Iterator/RandomAccessIterator.h"
|
||||
#include "Iterator/ContiguousIterator.h"
|
103
Redcraft.Utility/Source/Public/Iterator/RandomAccessIterator.h
Normal file
103
Redcraft.Utility/Source/Public/Iterator/RandomAccessIterator.h
Normal file
@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Iterator/Utility.h"
|
||||
#include "Iterator/Sentinel.h"
|
||||
#include "Iterator/BidirectionalIterator.h"
|
||||
#include "Miscellaneous/Compare.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
#if PLATFORM_COMPILER_GCC
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wnon-template-friend"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A concept specifies a type is a random access iterator.
|
||||
* Add the three-way comparison, addition, subtraction and subscript operators to the bidirectional iterator.
|
||||
*/
|
||||
template <typename I>
|
||||
concept CRandomAccessIterator = CBidirectionalIterator<I> && CTotallyOrdered<I> && CSizedSentinelFor<I, I>
|
||||
&& requires(I Iter, const I Jter, const ptrdiff N) {
|
||||
{ Iter += N } -> CSameAs<I&>;
|
||||
{ Jter + N } -> CSameAs<I >;
|
||||
{ N + Jter } -> CSameAs<I >;
|
||||
{ Iter -= N } -> CSameAs<I&>;
|
||||
{ Jter - N } -> CSameAs<I >;
|
||||
{ Jter[N] } -> CSameAs<TIteratorReference<I>>;
|
||||
};
|
||||
|
||||
/** This is an example of a random access iterator, indicate the traits that define a random access iterator. */
|
||||
template <CReference T>
|
||||
struct IRandomAccessIterator /* : IBidirectionalIterator<T> */
|
||||
{
|
||||
/** The element type of the indirectly readable type. See 'IIndirectlyReadable'. */
|
||||
using ElementType = TRemoveCVRef<T>;
|
||||
|
||||
/** Default constructor. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IRandomAccessIterator();
|
||||
|
||||
/** Copy constructor. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IRandomAccessIterator(const IRandomAccessIterator&);
|
||||
|
||||
/** Copy assignment operator. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
IRandomAccessIterator* operator=(const IRandomAccessIterator&);
|
||||
|
||||
/** Equality operator. See 'IIncrementable' and 'ISentinelFor'. */
|
||||
friend bool operator==(const IRandomAccessIterator&, const IRandomAccessIterator&);
|
||||
|
||||
/** Three-way comparison operator. */
|
||||
friend strong_ordering operator<=>(const IRandomAccessIterator& LHS, const IRandomAccessIterator& RHS);
|
||||
|
||||
/** Dereference operator. See 'IForwardIterator'. */
|
||||
T operator*() const;
|
||||
|
||||
/** Pre-increment operator. See 'IWeaklyIncrementable'. */
|
||||
IRandomAccessIterator& operator++();
|
||||
|
||||
/** Pre-decrement operator. See 'IBidirectionalIterator'. */
|
||||
IRandomAccessIterator& operator--();
|
||||
|
||||
/** Post-increment operator. See 'IIncrementable'. */
|
||||
IRandomAccessIterator operator++(int);
|
||||
|
||||
/** Post-decrement operator. See 'IBidirectionalIterator'. */
|
||||
IRandomAccessIterator operator--(int);
|
||||
|
||||
/** Addition assignment operator. */
|
||||
IRandomAccessIterator& operator+=(ptrdiff);
|
||||
|
||||
/** Subtraction assignment operator. */
|
||||
IRandomAccessIterator& operator-=(ptrdiff);
|
||||
|
||||
/** Addition operator. */
|
||||
IRandomAccessIterator operator+(ptrdiff) const;
|
||||
|
||||
/** Subtraction operator. */
|
||||
IRandomAccessIterator operator-(ptrdiff) const;
|
||||
|
||||
/** Addition operator. */
|
||||
friend IRandomAccessIterator operator+(ptrdiff, const IRandomAccessIterator&);
|
||||
|
||||
/** Subtraction operator. */
|
||||
friend ptrdiff operator-(const IRandomAccessIterator&, const IRandomAccessIterator&);
|
||||
|
||||
/** Subscript operator. */
|
||||
T operator[](ptrdiff) const;
|
||||
};
|
||||
|
||||
// Use 'IRandomAccessIterator<int>' represents a random access iterator
|
||||
static_assert(CRandomAccessIterator<IRandomAccessIterator<int&>>);
|
||||
static_assert( COutputIterator<IRandomAccessIterator<int&>, int>);
|
||||
|
||||
#if PLATFORM_COMPILER_GCC
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
111
Redcraft.Utility/Source/Public/Iterator/Sentinel.h
Normal file
111
Redcraft.Utility/Source/Public/Iterator/Sentinel.h
Normal file
@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Iterator/Utility.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
#if PLATFORM_COMPILER_GCC
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wnon-template-friend"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A concept specifies a type is a sentinel for an iterator and expression 'Iter == Sentinel' is valid.
|
||||
* In addition, the type must be default constructible and copyable.
|
||||
*/
|
||||
template <typename S, typename I>
|
||||
concept CSentinelFor = CSemiregular<S> && CInputOrOutputIterator<I> && CWeaklyEqualityComparable<S, I>;
|
||||
|
||||
/** This is an example of a sentinel for an iterator, indicate the traits that define a sentinel for an iterator. */
|
||||
template <CInputOrOutputIterator I>
|
||||
struct ISentinelFor
|
||||
{
|
||||
/** Default constructor. */
|
||||
ISentinelFor();
|
||||
|
||||
/** Copy constructor. */
|
||||
ISentinelFor(const ISentinelFor&);
|
||||
|
||||
/** Copy assignment operator. */
|
||||
ISentinelFor* operator=(const ISentinelFor&);
|
||||
|
||||
/** Equality operator. */
|
||||
bool operator==(const I&) const&;
|
||||
};
|
||||
|
||||
// Use 'ISentinelFor' represents a sentinel for an iterator.
|
||||
static_assert(CSentinelFor<ISentinelFor<IInputOrOutputIterator<int>>, IInputOrOutputIterator<int>>);
|
||||
|
||||
// The 'CSentinelFor' requires this code is valid.
|
||||
static_assert(
|
||||
requires(ISentinelFor<IInputOrOutputIterator<int>> Sentinel, IInputOrOutputIterator<int> Iter)
|
||||
{
|
||||
{ Iter == Sentinel } -> CBooleanTestable;
|
||||
{ Sentinel == Iter } -> CBooleanTestable;
|
||||
}
|
||||
);
|
||||
|
||||
/** Disable the 'CSizedSentinelFor' concept for specific types. */
|
||||
template <typename S, typename I>
|
||||
inline constexpr bool bDisableSizedSentinelFor = false;
|
||||
|
||||
/**
|
||||
* A concept specifies a type is a sized sentinel for an iterator and expressions 'Sentinel - Iter' and 'Iter - Sentinel' are valid,
|
||||
* and the 'Sentinel - Iter' is equal to negative 'Iter - Sentinel'.
|
||||
* In addition, the type must be default constructible and copyable.
|
||||
*/
|
||||
template <typename S, typename I>
|
||||
concept CSizedSentinelFor = CSentinelFor<S, I>
|
||||
&& !bDisableSizedSentinelFor<TRemoveCVRef<S>, TRemoveCVRef<I>>
|
||||
&& requires(const I& Iter, const S& Sentinel)
|
||||
{
|
||||
{ Sentinel - Iter } -> CSameAs<ptrdiff>;
|
||||
{ Iter - Sentinel } -> CSameAs<ptrdiff>;
|
||||
};
|
||||
|
||||
/** This is an example of a sized sentinel for an iterator, indicate the traits that define a sized sentinel for an iterator. */
|
||||
template <CInputOrOutputIterator I>
|
||||
struct ISizedSentinelFor /* : ISentinelFor<I> */
|
||||
{
|
||||
/** Default constructor. */
|
||||
ISizedSentinelFor();
|
||||
|
||||
/** Copy constructor. */
|
||||
ISizedSentinelFor(const ISizedSentinelFor&);
|
||||
|
||||
/** Copy assignment operator. */
|
||||
ISizedSentinelFor& operator=(const ISizedSentinelFor&);
|
||||
|
||||
/** Equality operator. */
|
||||
bool operator==(const I&) const&;
|
||||
|
||||
/** Subtraction operator. The 'Sentinel - Iter' is equal to negative 'Iter - Sentinel'. */
|
||||
friend ptrdiff operator-(const I&, const ISizedSentinelFor&);
|
||||
friend ptrdiff operator-(const ISizedSentinelFor&, const I&);
|
||||
};
|
||||
|
||||
// Use 'ISizedSentinelFor' represents a sized sentinel for an iterator.
|
||||
static_assert(CSizedSentinelFor<ISizedSentinelFor<IInputOrOutputIterator<int>>, IInputOrOutputIterator<int>>);
|
||||
|
||||
// The 'CSentinelFor' requires this code is valid.
|
||||
static_assert(
|
||||
requires(ISizedSentinelFor<IInputOrOutputIterator<int>> Sentinel, IInputOrOutputIterator<int> Iter)
|
||||
{
|
||||
{ Iter == Sentinel } -> CBooleanTestable;
|
||||
{ Sentinel == Iter } -> CBooleanTestable;
|
||||
{ Iter - Sentinel } -> CSameAs<ptrdiff>;
|
||||
{ Sentinel - Iter } -> CSameAs<ptrdiff>;
|
||||
}
|
||||
);
|
||||
|
||||
#if PLATFORM_COMPILER_GCC
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
325
Redcraft.Utility/Source/Public/Iterator/Utility.h
Normal file
325
Redcraft.Utility/Source/Public/Iterator/Utility.h
Normal file
@ -0,0 +1,325 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Templates/Utility.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
NAMESPACE_PRIVATE_BEGIN
|
||||
|
||||
template <typename T> using TWithReference = T&;
|
||||
|
||||
template <typename I> struct TIteratorElementImpl { using Type = typename I::ElementType; };
|
||||
template <typename T> struct TIteratorElementImpl<T*> { using Type = TRemoveCV<T>; };
|
||||
|
||||
template <typename I> struct TIteratorPointerImpl { using Type = void; };
|
||||
template <typename T> struct TIteratorPointerImpl<T*> { using Type = T*; };
|
||||
|
||||
template <typename I> requires (requires(I& Iter) { { Iter.operator->() } -> CPointer; })
|
||||
struct TIteratorPointerImpl<I> { using Type = decltype(DeclVal<I&>().operator->()); };
|
||||
|
||||
NAMESPACE_PRIVATE_END
|
||||
|
||||
template <typename T>
|
||||
concept CReferenceable = requires { typename NAMESPACE_PRIVATE::TWithReference<T>; };
|
||||
|
||||
template <typename T>
|
||||
concept CDereferenceable = requires(T& A) { { *A } -> CReferenceable; };
|
||||
|
||||
template <typename I>
|
||||
using TIteratorElement = typename NAMESPACE_PRIVATE::TIteratorElementImpl<TRemoveCVRef<I>>::Type;
|
||||
|
||||
template <typename I>
|
||||
using TIteratorPointer = typename NAMESPACE_PRIVATE::TIteratorPointerImpl<TRemoveCVRef<I>>::Type;
|
||||
|
||||
template <CReferenceable I>
|
||||
using TIteratorReference = decltype(*DeclVal<I&>());
|
||||
|
||||
template <CReferenceable I> requires (requires(I& Iter) { { MoveTemp(*Iter) } -> CReferenceable; })
|
||||
using TIteratorRValueReference = decltype(MoveTemp(*DeclVal<I&>()));
|
||||
|
||||
NAMESPACE_PRIVATE_BEGIN
|
||||
|
||||
template <typename I>
|
||||
concept CIndirectlyReadable =
|
||||
requires(const I Iter)
|
||||
{
|
||||
typename TIteratorElement<I>;
|
||||
typename TIteratorReference<I>;
|
||||
typename TIteratorRValueReference<I>;
|
||||
{ *Iter } -> CSameAs<TIteratorReference<I>>;
|
||||
{ MoveTemp(*Iter) } -> CSameAs<TIteratorRValueReference<I>>;
|
||||
}
|
||||
&& CSameAs<TIteratorElement<I>, TRemoveCVRef<TIteratorElement<I>>>
|
||||
&& CCommonReference<TIteratorReference<I>&&, TIteratorElement<I>&>
|
||||
&& CCommonReference<TIteratorReference<I>&&, TIteratorRValueReference<I>&&>
|
||||
&& CCommonReference<TIteratorRValueReference<I>&&, const TIteratorElement<I>&>;
|
||||
|
||||
NAMESPACE_PRIVATE_END
|
||||
|
||||
/** A concept specifies a type is indirectly readable by expression '*Iter'. */
|
||||
template <typename I>
|
||||
concept CIndirectlyReadable = NAMESPACE_PRIVATE::CIndirectlyReadable<TRemoveCVRef<I>>;
|
||||
|
||||
/** This is an example of an indirectly readable type, indicate the traits that define an indirectly readable type. */
|
||||
template <CReferenceable T>
|
||||
struct IIndirectlyReadable
|
||||
{
|
||||
/**
|
||||
* The element type of the indirectly readable type.
|
||||
* It must be a non-const, non-volatile and non-reference type and can be referenced, i.e. not a void type.
|
||||
*/
|
||||
using ElementType = TRemoveCVRef<T>;
|
||||
|
||||
/**
|
||||
* Indirectly read the element from the indirectly readable type.
|
||||
* The return type may not be 'const ElementType&', this concept only requires that the return type
|
||||
* and 'ElementType' has some relationship, such as copy constructible to 'ElementType' if the type is copyable.
|
||||
* This means that returning a proxy class castable to 'ElementType' is also valid.
|
||||
* If this is an iterator adaptor, use 'decltype(auto)' to forward the return value.
|
||||
*/
|
||||
T operator*() const;
|
||||
};
|
||||
|
||||
// Use 'IIndirectlyReadable<int>' represents an indirectly readable type and 'int' is the regular element type.
|
||||
static_assert(CIndirectlyReadable<IIndirectlyReadable<int>> && CRegular<int>);
|
||||
|
||||
// The 'CIndirectlyReadable' requires this code is valid.
|
||||
static_assert(
|
||||
requires(IIndirectlyReadable<int> Iter, int& A)
|
||||
{
|
||||
A = *Iter;
|
||||
}
|
||||
);
|
||||
|
||||
/** A concept specifies a type is indirectly writable by expression '*Iter = A'. */
|
||||
template <typename I, typename T>
|
||||
concept CIndirectlyWritable =
|
||||
requires(I&& Iter, T&& A)
|
||||
{
|
||||
*Iter = Forward<T>(A);
|
||||
*Forward<I>(Iter) = Forward<T>(A);
|
||||
const_cast<const TIteratorReference<I>&&>(*Iter) = Forward<T>(A);
|
||||
const_cast<const TIteratorReference<I>&&>(*Forward<I>(Iter)) = Forward<T>(A);
|
||||
};
|
||||
|
||||
/** This is an example of an indirectly writable type, indicate the traits that define an indirectly writable type. */
|
||||
template <CReference T>
|
||||
struct IIndirectlyWritable
|
||||
{
|
||||
/**
|
||||
* Indirectly write the element from the indirectly writable type.
|
||||
* The return type may not be 'T&', this concept only requires that the return type and 'T' has some relationship,
|
||||
* such as can be assigned from 'T&' if the type is copyable or 'T&&' if the type is movable.
|
||||
* This means that returning a proxy class can be assigned from 'T' is also valid.
|
||||
* If this is also an indirectly readable type, the equivalent value is read after writing.
|
||||
* If this is an iterator adaptor, use 'decltype(auto)' to forward the return value.
|
||||
*/
|
||||
T operator*() const;
|
||||
};
|
||||
|
||||
// Use 'IIndirectlyWritable<int>' represents an indirectly writable type and 'int' is the regular element type.
|
||||
static_assert(CIndirectlyWritable<IIndirectlyWritable<int&>, int> && CRegular<int>);
|
||||
|
||||
// The 'CIndirectlyWritable' requires this code is valid.
|
||||
static_assert(
|
||||
requires(IIndirectlyWritable<int&> Iter, int& A)
|
||||
{
|
||||
*Iter = A;
|
||||
}
|
||||
);
|
||||
|
||||
/** A concept specifies a type is incrementable by expression '++Iter' and the type must be movable. */
|
||||
template <typename I>
|
||||
concept CWeaklyIncrementable = CMovable<I>
|
||||
&& requires(I Iter) { { ++Iter } -> CSameAs<I&>; Iter++; };
|
||||
|
||||
/** This is an example of a weakly incrementable type, indicate the traits that define a weakly incrementable type. */
|
||||
struct IWeaklyIncrementable
|
||||
{
|
||||
/** Move constructor. */
|
||||
IWeaklyIncrementable(IWeaklyIncrementable&&);
|
||||
|
||||
/** Move assignment operator. */
|
||||
IWeaklyIncrementable* operator=(IWeaklyIncrementable&&);
|
||||
|
||||
/** Pre-increment operator. */
|
||||
IWeaklyIncrementable& operator++();
|
||||
|
||||
/**
|
||||
* Post-increment operator.
|
||||
* Specify, the concept not requires the return type is any specific type, so the return type can be 'void'.
|
||||
*/
|
||||
void operator++(int);
|
||||
};
|
||||
|
||||
// Use 'IWeaklyIncrementable' represents a weakly incrementable type.
|
||||
static_assert(CWeaklyIncrementable<IWeaklyIncrementable>);
|
||||
|
||||
/**
|
||||
* A concept specifies a type is incrementable by expression 'Iter++' and the expression returns the original value.
|
||||
* In addition, the type must be default constructible, copyable and weakly equality comparable.
|
||||
*/
|
||||
template <typename I>
|
||||
concept CIncrementable = CRegular<I> && CWeaklyIncrementable<I>
|
||||
&& requires(I Iter) { { Iter++ } -> CSameAs<I>; };
|
||||
|
||||
/**
|
||||
* This is an example of an incrementable type, indicate the traits that define an incrementable type.
|
||||
* The copy object of this type produced by copy constructor, copy assignment or post-increment
|
||||
* should produce the same effect as the original object when incrementing.
|
||||
*/
|
||||
struct IIncrementable /* : IWeaklyIncrementable */
|
||||
{
|
||||
/** Default constructor. */
|
||||
IIncrementable();
|
||||
|
||||
/** Copy constructor. */
|
||||
IIncrementable(const IIncrementable&);
|
||||
|
||||
/** Copy assignment operator. */
|
||||
IIncrementable* operator=(const IIncrementable&);
|
||||
|
||||
/** Equality operator. */
|
||||
friend bool operator==(const IIncrementable&, const IIncrementable&);
|
||||
|
||||
/** Pre-increment operator. See 'IWeaklyIncrementable'. */
|
||||
IIncrementable& operator++();
|
||||
|
||||
/** Post-increment operator. */
|
||||
IIncrementable operator++(int);
|
||||
};
|
||||
|
||||
// Use 'IIncrementable' represents an incrementable type.
|
||||
static_assert(CIncrementable<IIncrementable>);
|
||||
|
||||
/**
|
||||
* A concept specifies a type is potentially an iterator. It only requires weakly incrementable and dereferenceable.
|
||||
* This concept should only be used in scenarios where the specific type of the iterator is not important, such as iterator adapters.
|
||||
*/
|
||||
template <typename I>
|
||||
concept CInputOrOutputIterator = CWeaklyIncrementable<I>
|
||||
&& requires(I Iter) { { *Iter } -> CReferenceable; };
|
||||
|
||||
/** This is an example of an input or output iterator, indicate the traits that define an input or output iterator. */
|
||||
template <CReferenceable T>
|
||||
struct IInputOrOutputIterator /* : IWeaklyIncrementable */
|
||||
{
|
||||
/** Move constructor. See 'IWeaklyIncrementable'. */
|
||||
IInputOrOutputIterator(IInputOrOutputIterator&&);
|
||||
|
||||
/** Move assignment operator. See 'IWeaklyIncrementable'. */
|
||||
IInputOrOutputIterator* operator=(IInputOrOutputIterator&&);
|
||||
|
||||
/** Pre-increment operator. See 'IWeaklyIncrementable'. */
|
||||
IInputOrOutputIterator& operator++();
|
||||
|
||||
/** Post-increment operator. See 'IWeaklyIncrementable'. */
|
||||
void operator++(int);
|
||||
|
||||
/** Dereference operator. It does not matter what the return type is, as long as it is referenceable. */
|
||||
T operator*() const;
|
||||
};
|
||||
|
||||
// Use 'IInputOrOutputIterator' represents an input or output iterator.
|
||||
static_assert(CInputOrOutputIterator<IInputOrOutputIterator<int>>);
|
||||
|
||||
/** A concept specifies a type is an input iterator. */
|
||||
template <typename I>
|
||||
concept CInputIterator = CInputOrOutputIterator<I> && CIndirectlyReadable<I>;
|
||||
|
||||
/** This is an example of an input iterator, indicate the traits that define an input iterator. */
|
||||
template <CReferenceable T>
|
||||
struct IInputIterator /* : IInputOrOutputIterator, IIndirectlyReadable */
|
||||
{
|
||||
/** The element type of the indirectly readable type. See 'IIndirectlyReadable'. */
|
||||
using ElementType = TRemoveCVRef<T>;
|
||||
|
||||
/** Move constructor. See 'IWeaklyIncrementable'. */
|
||||
IInputIterator(IInputIterator&&);
|
||||
|
||||
/** Move assignment operator. See 'IWeaklyIncrementable'. */
|
||||
IInputIterator* operator=(IInputIterator&&);
|
||||
|
||||
/** Indirectly read the element from the indirectly readable type. See 'IIndirectlyReadable'. */
|
||||
T operator*() const;
|
||||
|
||||
/** Pre-increment operator. See 'IWeaklyIncrementable'. */
|
||||
IInputIterator& operator++();
|
||||
|
||||
/** Post-increment operator. See 'IWeaklyIncrementable'. */
|
||||
void operator++(int);
|
||||
};
|
||||
|
||||
// Use 'IInputIterator<int>' represents an input iterator and 'int' is the regular element type.
|
||||
static_assert(CInputIterator<IInputIterator<int>> && CRegular<int>);
|
||||
|
||||
// The 'CInputIterator' requires this code is valid.
|
||||
static_assert(
|
||||
requires(IInputIterator<int> Iter, int& A)
|
||||
{
|
||||
++Iter;
|
||||
Iter++;
|
||||
A = *++Iter;
|
||||
A = *Iter;
|
||||
}
|
||||
);
|
||||
|
||||
/** A concept specifies a type is an output iterator and expression '*Iter++ = A' is valid to write the element. */
|
||||
template <typename I, typename T>
|
||||
concept COutputIterator = CInputOrOutputIterator<I> && CIndirectlyWritable<I, T>
|
||||
&& requires(I Iter) { { Iter++ } -> CIndirectlyWritable<T>; };
|
||||
|
||||
/** This is an example of an output iterator, indicate the traits that define an output iterator. */
|
||||
template <CReference T>
|
||||
struct IOutputIterator /* : IInputOrOutputIterator, IIndirectlyWritable<T> */
|
||||
{
|
||||
/** Move constructor. See 'IWeaklyIncrementable'. */
|
||||
IOutputIterator(IOutputIterator&&);
|
||||
|
||||
/** Move assignment operator. See 'IWeaklyIncrementable'. */
|
||||
IOutputIterator* operator=(IOutputIterator&&);
|
||||
|
||||
/** Indirectly write the element from the indirectly writable type. See 'IIndirectlyWritable'. */
|
||||
T operator*() const;
|
||||
|
||||
/** Pre-increment operator. See 'IWeaklyIncrementable'. */
|
||||
IOutputIterator& operator++();
|
||||
|
||||
/**
|
||||
* Post-increment operator.
|
||||
* Specify, the concept not requires the return type is self type,
|
||||
* but requires the expression '*Iter++ = A;' is equivalent to '*Iter = A; ++Iter;'.
|
||||
* This means that returning a proxy class that satisfies 'CIndirectlyWritable<T>' is also valid.
|
||||
* See 'IWeaklyIncrementable'.
|
||||
*/
|
||||
IIndirectlyWritable<T> operator++(int);
|
||||
};
|
||||
|
||||
// Use 'IOutputIterator<int>' represents an output iterator and 'int' is the regular element type.
|
||||
static_assert(COutputIterator<IOutputIterator<int&>, int> && CRegular<int>);
|
||||
|
||||
// The 'CInputIterator' requires this code is valid.
|
||||
static_assert(
|
||||
requires(IOutputIterator<int&> Iter, int& A)
|
||||
{
|
||||
++Iter;
|
||||
Iter++;
|
||||
*++Iter = A;
|
||||
*Iter++ = A;
|
||||
*Iter = A;
|
||||
}
|
||||
);
|
||||
|
||||
#define ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT public: \
|
||||
NODISCARD FORCEINLINE constexpr auto begin() { return Begin(); } \
|
||||
NODISCARD FORCEINLINE constexpr auto begin() const { return Begin(); } \
|
||||
NODISCARD FORCEINLINE constexpr auto end() { return End(); } \
|
||||
NODISCARD FORCEINLINE constexpr auto end() const { return End(); }
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
@ -3,6 +3,7 @@
|
||||
#include "CoreTypes.h"
|
||||
#include "Memory/Address.h"
|
||||
#include "Templates/Invoke.h"
|
||||
#include "Iterator/Iterator.h"
|
||||
#include "Templates/Utility.h"
|
||||
#include "Templates/Noncopyable.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
@ -13,128 +14,17 @@ NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
NAMESPACE_PRIVATE_BEGIN
|
||||
|
||||
template <typename T> using WithReference = T&;
|
||||
|
||||
template <typename I> struct TIteratorElementType { using Type = typename I::ElementType; };
|
||||
template <typename T> struct TIteratorElementType<T*> { using Type = TRemoveCV<T>; };
|
||||
|
||||
template <typename I> struct TIteratorPointerType { using Type = void; };
|
||||
template <typename T> struct TIteratorPointerType<T*> { using Type = T*; };
|
||||
|
||||
template <typename I> requires (requires(I& Iter) { { Iter.operator->() } -> CPointer; })
|
||||
struct TIteratorPointerType<I> { using Type = decltype(DeclVal<I&>().operator->()); };
|
||||
|
||||
NAMESPACE_PRIVATE_END
|
||||
|
||||
template <typename T>
|
||||
concept CReferenceable = requires { typename NAMESPACE_PRIVATE::WithReference<T>; };
|
||||
|
||||
template <typename T>
|
||||
concept CDereferenceable = requires(T& A) { { *A } -> CReferenceable; };
|
||||
template <typename I>
|
||||
using TIteratorElementType = TIteratorElement<I>;
|
||||
|
||||
template <typename I>
|
||||
using TIteratorElementType = typename NAMESPACE_PRIVATE::TIteratorElementType<TRemoveCVRef<I>>::Type;
|
||||
|
||||
template <typename I>
|
||||
using TIteratorPointerType = typename NAMESPACE_PRIVATE::TIteratorPointerType<TRemoveCVRef<I>>::Type;
|
||||
using TIteratorPointerType = TIteratorPointer<I>;
|
||||
|
||||
template <CReferenceable I>
|
||||
using TIteratorReferenceType = decltype(*DeclVal<I&>());
|
||||
using TIteratorReferenceType = TIteratorReference<I>;
|
||||
|
||||
template <CReferenceable I> requires (requires(I& Iter) { { MoveTemp(*Iter) } -> CReferenceable; })
|
||||
using TIteratorRValueReferenceType = decltype(MoveTemp(*DeclVal<I&>()));
|
||||
|
||||
template <typename I>
|
||||
concept CIndirectlyReadable =
|
||||
requires(const TRemoveCVRef<I> Iter)
|
||||
{
|
||||
typename TIteratorElementType<I>;
|
||||
typename TIteratorReferenceType<I>;
|
||||
typename TIteratorRValueReferenceType<I>;
|
||||
{ *Iter } -> CSameAs<TIteratorReferenceType<I>>;
|
||||
{ MoveTemp(*Iter) } -> CSameAs<TIteratorRValueReferenceType<I>>;
|
||||
}
|
||||
&& CSameAs<TIteratorElementType<I>, TRemoveCVRef<TIteratorElementType<I>>>
|
||||
&& CCommonReference<TIteratorReferenceType<I>&&, TIteratorElementType<I>&>
|
||||
&& CCommonReference<TIteratorReferenceType<I>&&, TIteratorRValueReferenceType<I>&&>
|
||||
&& CCommonReference<TIteratorRValueReferenceType<I>&&, const TIteratorElementType<I>&>;
|
||||
|
||||
template <typename I, typename T>
|
||||
concept CIndirectlyWritable =
|
||||
requires(I&& Iter, T&& A)
|
||||
{
|
||||
*Iter = Forward<T>(A);
|
||||
*Forward<I>(Iter) = Forward<T>(A);
|
||||
const_cast<const TIteratorReferenceType<I>&&>(*Iter) = Forward<T>(A);
|
||||
const_cast<const TIteratorReferenceType<I>&&>(*Forward<I>(Iter)) = Forward<T>(A);
|
||||
};
|
||||
|
||||
template <typename I>
|
||||
concept CWeaklyIncrementable = CMovable<I>
|
||||
&& requires(I Iter) { { ++Iter } -> CSameAs<I&>; Iter++; };
|
||||
|
||||
template <typename I>
|
||||
concept CIncrementable = CRegular<I> && CWeaklyIncrementable<I>
|
||||
&& requires(I Iter) { { Iter++ } -> CSameAs<I>; };
|
||||
|
||||
template <typename I>
|
||||
concept CInputOrOutputIterator = CWeaklyIncrementable<I>
|
||||
&& requires(I Iter) { { *Iter } -> CReferenceable; };
|
||||
|
||||
template <typename S, typename I>
|
||||
concept CSentinelFor = CSemiregular<S> && CInputOrOutputIterator<I> && CWeaklyEqualityComparable<S, I>;
|
||||
|
||||
template <typename S, typename I>
|
||||
inline constexpr bool bDisableSizedSentinelFor = false;
|
||||
|
||||
template <typename S, typename I>
|
||||
concept CSizedSentinelFor = CSentinelFor<S, I> && CPartiallyOrdered<S, I>
|
||||
&& !bDisableSizedSentinelFor<TRemoveCV<S>, TRemoveCV<I>>
|
||||
&& requires(const I& Iter, const S& Sentinel)
|
||||
{
|
||||
{ Sentinel - Iter } -> CSameAs<ptrdiff>;
|
||||
{ Iter - Sentinel } -> CSameAs<ptrdiff>;
|
||||
};
|
||||
|
||||
template <typename I>
|
||||
concept CInputIterator = CInputOrOutputIterator<I> && CIndirectlyReadable<I>;
|
||||
|
||||
template <typename I, typename T>
|
||||
concept COutputIterator = CInputOrOutputIterator<I> && CIndirectlyWritable<I, T>
|
||||
&& requires(I Iter, T&& A) { *Iter++ = Forward<T>(A); };
|
||||
|
||||
template <typename I>
|
||||
concept CForwardIterator = CInputIterator<I> && CIncrementable<I> && CSentinelFor<I, I>;
|
||||
|
||||
template <typename I>
|
||||
concept CBidirectionalIterator = CForwardIterator<I>
|
||||
&& requires(I Iter) {
|
||||
{ --Iter } -> CSameAs<I&>;
|
||||
{ Iter-- } -> CSameAs<I >;
|
||||
};
|
||||
|
||||
template <typename I>
|
||||
concept CRandomAccessIterator = CBidirectionalIterator<I> && CTotallyOrdered<I> && CSizedSentinelFor<I, I>
|
||||
&& requires(I Iter, const I Jter, const ptrdiff N) {
|
||||
{ Iter += N } -> CSameAs<I&>;
|
||||
{ Jter + N } -> CSameAs<I >;
|
||||
{ N + Jter } -> CSameAs<I >;
|
||||
{ Iter -= N } -> CSameAs<I&>;
|
||||
{ Jter - N } -> CSameAs<I >;
|
||||
{ Jter[N] } -> CSameAs<TIteratorReferenceType<I>>;
|
||||
};
|
||||
|
||||
template <typename I>
|
||||
concept CContiguousIterator = CRandomAccessIterator<I> && CLValueReference<TIteratorReferenceType<I>>
|
||||
&& CSameAs<TIteratorElementType<I>, TRemoveCVRef<TIteratorReferenceType<I>>>
|
||||
&& requires(I& Iter)
|
||||
{
|
||||
{ ToAddress(Iter) } -> CSameAs<TAddPointer<TIteratorReferenceType<I>>>;
|
||||
};
|
||||
|
||||
static_assert(CContiguousIterator<int32*>);
|
||||
using TIteratorRValueReferenceType = TIteratorRValueReference<I>;
|
||||
|
||||
NAMESPACE_BEGIN(Iteration)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user