diff --git a/Redcraft.Utility/Source/Public/Iterator/BidirectionalIterator.h b/Redcraft.Utility/Source/Public/Iterator/BidirectionalIterator.h new file mode 100644 index 0000000..49495f0 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Iterator/BidirectionalIterator.h @@ -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 +concept CBidirectionalIterator = CForwardIterator + && requires(I Iter) { + { --Iter } -> CSameAs; + { Iter-- } -> CSameAs; + }; + +/** + * 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 +struct IBidirectionalIterator /* : IForwardIterator */ +{ + /** The element type of the indirectly readable type. See 'IIndirectlyReadable'. */ + using ElementType = TRemoveCVRef; + + /** 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' represents a bidirectional iterator. +static_assert(CBidirectionalIterator>); +static_assert( COutputIterator, int>); + +#if PLATFORM_COMPILER_GCC +# pragma GCC diagnostic pop +#endif + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Iterator/ContiguousIterator.h b/Redcraft.Utility/Source/Public/Iterator/ContiguousIterator.h new file mode 100644 index 0000000..8825e28 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Iterator/ContiguousIterator.h @@ -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 +concept CContiguousIterator = CRandomAccessIterator && CLValueReference> + && CSameAs, TRemoveCVRef>> + && CSameAs, TAddPointer>> + && requires(I& Iter) + { + { ToAddress(Iter) } -> CSameAs>>; + }; + +/** This is an example of a contiguous iterator, indicate the traits that define a contiguous iterator. */ +template +struct IContiguousIterator /* : IBidirectionalIterator */ +{ + /** The element type of the indirectly readable type. See 'IIndirectlyReadable'. */ + using ElementType = TRemoveCVRef; + + /** 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 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' represents a contiguous iterator +static_assert(CContiguousIterator>); +static_assert( COutputIterator, int>); + +// The 'int*' is the most typical example of a contiguous iterator +static_assert(CContiguousIterator); + +#if PLATFORM_COMPILER_GCC +# pragma GCC diagnostic pop +#endif + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Iterator/ForwardIterator.h b/Redcraft.Utility/Source/Public/Iterator/ForwardIterator.h new file mode 100644 index 0000000..d6b9f08 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Iterator/ForwardIterator.h @@ -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 +concept CForwardIterator = CInputIterator && CIncrementable && CSentinelFor; + +/** This is an example of a forward iterator, indicate the traits that define a forward iterator. */ +template +struct IForwardIterator /* : IInputIterator, IIncrementable, ISentinelFor */ +{ + /** The element type of the indirectly readable type. See 'IIndirectlyReadable'. */ + using ElementType = TRemoveCVRef; + + /** 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' represents a forward iterator. +static_assert(CForwardIterator>); +static_assert( COutputIterator, int>); + +#if PLATFORM_COMPILER_GCC +# pragma GCC diagnostic pop +#endif + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Iterator/Iterator.h b/Redcraft.Utility/Source/Public/Iterator/Iterator.h new file mode 100644 index 0000000..8e21b7f --- /dev/null +++ b/Redcraft.Utility/Source/Public/Iterator/Iterator.h @@ -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" diff --git a/Redcraft.Utility/Source/Public/Iterator/RandomAccessIterator.h b/Redcraft.Utility/Source/Public/Iterator/RandomAccessIterator.h new file mode 100644 index 0000000..46c282d --- /dev/null +++ b/Redcraft.Utility/Source/Public/Iterator/RandomAccessIterator.h @@ -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 +concept CRandomAccessIterator = CBidirectionalIterator && CTotallyOrdered && CSizedSentinelFor + && requires(I Iter, const I Jter, const ptrdiff N) { + { Iter += N } -> CSameAs; + { Jter + N } -> CSameAs; + { N + Jter } -> CSameAs; + { Iter -= N } -> CSameAs; + { Jter - N } -> CSameAs; + { Jter[N] } -> CSameAs>; + }; + +/** This is an example of a random access iterator, indicate the traits that define a random access iterator. */ +template +struct IRandomAccessIterator /* : IBidirectionalIterator */ +{ + /** The element type of the indirectly readable type. See 'IIndirectlyReadable'. */ + using ElementType = TRemoveCVRef; + + /** 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' represents a random access iterator +static_assert(CRandomAccessIterator>); +static_assert( COutputIterator, int>); + +#if PLATFORM_COMPILER_GCC +# pragma GCC diagnostic pop +#endif + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Iterator/Sentinel.h b/Redcraft.Utility/Source/Public/Iterator/Sentinel.h new file mode 100644 index 0000000..c8c0615 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Iterator/Sentinel.h @@ -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 +concept CSentinelFor = CSemiregular && CInputOrOutputIterator && CWeaklyEqualityComparable; + +/** This is an example of a sentinel for an iterator, indicate the traits that define a sentinel for an iterator. */ +template +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>, IInputOrOutputIterator>); + +// The 'CSentinelFor' requires this code is valid. +static_assert( + requires(ISentinelFor> Sentinel, IInputOrOutputIterator Iter) + { + { Iter == Sentinel } -> CBooleanTestable; + { Sentinel == Iter } -> CBooleanTestable; + } +); + +/** Disable the 'CSizedSentinelFor' concept for specific types. */ +template +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 +concept CSizedSentinelFor = CSentinelFor + && !bDisableSizedSentinelFor, TRemoveCVRef> + && requires(const I& Iter, const S& Sentinel) + { + { Sentinel - Iter } -> CSameAs; + { Iter - Sentinel } -> CSameAs; + }; + +/** This is an example of a sized sentinel for an iterator, indicate the traits that define a sized sentinel for an iterator. */ +template +struct ISizedSentinelFor /* : ISentinelFor */ +{ + /** 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>, IInputOrOutputIterator>); + +// The 'CSentinelFor' requires this code is valid. +static_assert( + requires(ISizedSentinelFor> Sentinel, IInputOrOutputIterator Iter) + { + { Iter == Sentinel } -> CBooleanTestable; + { Sentinel == Iter } -> CBooleanTestable; + { Iter - Sentinel } -> CSameAs; + { Sentinel - Iter } -> CSameAs; + } +); + +#if PLATFORM_COMPILER_GCC +# pragma GCC diagnostic pop +#endif + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Iterator/Utility.h b/Redcraft.Utility/Source/Public/Iterator/Utility.h new file mode 100644 index 0000000..bd24d4b --- /dev/null +++ b/Redcraft.Utility/Source/Public/Iterator/Utility.h @@ -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 using TWithReference = T&; + +template struct TIteratorElementImpl { using Type = typename I::ElementType; }; +template struct TIteratorElementImpl { using Type = TRemoveCV; }; + +template struct TIteratorPointerImpl { using Type = void; }; +template struct TIteratorPointerImpl { using Type = T*; }; + +template requires (requires(I& Iter) { { Iter.operator->() } -> CPointer; }) +struct TIteratorPointerImpl { using Type = decltype(DeclVal().operator->()); }; + +NAMESPACE_PRIVATE_END + +template +concept CReferenceable = requires { typename NAMESPACE_PRIVATE::TWithReference; }; + +template +concept CDereferenceable = requires(T& A) { { *A } -> CReferenceable; }; + +template +using TIteratorElement = typename NAMESPACE_PRIVATE::TIteratorElementImpl>::Type; + +template +using TIteratorPointer = typename NAMESPACE_PRIVATE::TIteratorPointerImpl>::Type; + +template +using TIteratorReference = decltype(*DeclVal()); + +template requires (requires(I& Iter) { { MoveTemp(*Iter) } -> CReferenceable; }) +using TIteratorRValueReference = decltype(MoveTemp(*DeclVal())); + +NAMESPACE_PRIVATE_BEGIN + +template +concept CIndirectlyReadable = + requires(const I Iter) + { + typename TIteratorElement; + typename TIteratorReference; + typename TIteratorRValueReference; + { *Iter } -> CSameAs>; + { MoveTemp(*Iter) } -> CSameAs>; + } + && CSameAs, TRemoveCVRef>> + && CCommonReference&&, TIteratorElement&> + && CCommonReference&&, TIteratorRValueReference&&> + && CCommonReference&&, const TIteratorElement&>; + +NAMESPACE_PRIVATE_END + +/** A concept specifies a type is indirectly readable by expression '*Iter'. */ +template +concept CIndirectlyReadable = NAMESPACE_PRIVATE::CIndirectlyReadable>; + +/** This is an example of an indirectly readable type, indicate the traits that define an indirectly readable type. */ +template +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; + + /** + * 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' represents an indirectly readable type and 'int' is the regular element type. +static_assert(CIndirectlyReadable> && CRegular); + +// The 'CIndirectlyReadable' requires this code is valid. +static_assert( + requires(IIndirectlyReadable Iter, int& A) + { + A = *Iter; + } +); + +/** A concept specifies a type is indirectly writable by expression '*Iter = A'. */ +template +concept CIndirectlyWritable = + requires(I&& Iter, T&& A) + { + *Iter = Forward(A); + *Forward(Iter) = Forward(A); + const_cast&&>(*Iter) = Forward(A); + const_cast&&>(*Forward(Iter)) = Forward(A); + }; + +/** This is an example of an indirectly writable type, indicate the traits that define an indirectly writable type. */ +template +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' represents an indirectly writable type and 'int' is the regular element type. +static_assert(CIndirectlyWritable, int> && CRegular); + +// The 'CIndirectlyWritable' requires this code is valid. +static_assert( + requires(IIndirectlyWritable Iter, int& A) + { + *Iter = A; + } +); + +/** A concept specifies a type is incrementable by expression '++Iter' and the type must be movable. */ +template +concept CWeaklyIncrementable = CMovable + && requires(I Iter) { { ++Iter } -> CSameAs; 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); + +/** + * 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 +concept CIncrementable = CRegular && CWeaklyIncrementable + && requires(I Iter) { { Iter++ } -> CSameAs; }; + +/** + * 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); + +/** + * 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 +concept CInputOrOutputIterator = CWeaklyIncrementable + && 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 +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>); + +/** A concept specifies a type is an input iterator. */ +template +concept CInputIterator = CInputOrOutputIterator && CIndirectlyReadable; + +/** This is an example of an input iterator, indicate the traits that define an input iterator. */ +template +struct IInputIterator /* : IInputOrOutputIterator, IIndirectlyReadable */ +{ + /** The element type of the indirectly readable type. See 'IIndirectlyReadable'. */ + using ElementType = TRemoveCVRef; + + /** 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' represents an input iterator and 'int' is the regular element type. +static_assert(CInputIterator> && CRegular); + +// The 'CInputIterator' requires this code is valid. +static_assert( + requires(IInputIterator 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 +concept COutputIterator = CInputOrOutputIterator && CIndirectlyWritable + && requires(I Iter) { { Iter++ } -> CIndirectlyWritable; }; + +/** This is an example of an output iterator, indicate the traits that define an output iterator. */ +template +struct IOutputIterator /* : IInputOrOutputIterator, IIndirectlyWritable */ +{ + /** 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' is also valid. + * See 'IWeaklyIncrementable'. + */ + IIndirectlyWritable operator++(int); +}; + +// Use 'IOutputIterator' represents an output iterator and 'int' is the regular element type. +static_assert(COutputIterator, int> && CRegular); + +// The 'CInputIterator' requires this code is valid. +static_assert( + requires(IOutputIterator 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 diff --git a/Redcraft.Utility/Source/Public/Miscellaneous/Iterator.h b/Redcraft.Utility/Source/Public/Miscellaneous/Iterator.h index 7153349..4f72399 100644 --- a/Redcraft.Utility/Source/Public/Miscellaneous/Iterator.h +++ b/Redcraft.Utility/Source/Public/Miscellaneous/Iterator.h @@ -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 using WithReference = T&; - -template struct TIteratorElementType { using Type = typename I::ElementType; }; -template struct TIteratorElementType { using Type = TRemoveCV; }; - -template struct TIteratorPointerType { using Type = void; }; -template struct TIteratorPointerType { using Type = T*; }; - -template requires (requires(I& Iter) { { Iter.operator->() } -> CPointer; }) -struct TIteratorPointerType { using Type = decltype(DeclVal().operator->()); }; - -NAMESPACE_PRIVATE_END - -template -concept CReferenceable = requires { typename NAMESPACE_PRIVATE::WithReference; }; - -template -concept CDereferenceable = requires(T& A) { { *A } -> CReferenceable; }; +template +using TIteratorElementType = TIteratorElement; template -using TIteratorElementType = typename NAMESPACE_PRIVATE::TIteratorElementType>::Type; - -template -using TIteratorPointerType = typename NAMESPACE_PRIVATE::TIteratorPointerType>::Type; +using TIteratorPointerType = TIteratorPointer; template -using TIteratorReferenceType = decltype(*DeclVal()); +using TIteratorReferenceType = TIteratorReference; template requires (requires(I& Iter) { { MoveTemp(*Iter) } -> CReferenceable; }) -using TIteratorRValueReferenceType = decltype(MoveTemp(*DeclVal())); - -template -concept CIndirectlyReadable = - requires(const TRemoveCVRef Iter) - { - typename TIteratorElementType; - typename TIteratorReferenceType; - typename TIteratorRValueReferenceType; - { *Iter } -> CSameAs>; - { MoveTemp(*Iter) } -> CSameAs>; - } - && CSameAs, TRemoveCVRef>> - && CCommonReference&&, TIteratorElementType&> - && CCommonReference&&, TIteratorRValueReferenceType&&> - && CCommonReference&&, const TIteratorElementType&>; - -template -concept CIndirectlyWritable = - requires(I&& Iter, T&& A) - { - *Iter = Forward(A); - *Forward(Iter) = Forward(A); - const_cast&&>(*Iter) = Forward(A); - const_cast&&>(*Forward(Iter)) = Forward(A); - }; - -template -concept CWeaklyIncrementable = CMovable - && requires(I Iter) { { ++Iter } -> CSameAs; Iter++; }; - -template -concept CIncrementable = CRegular && CWeaklyIncrementable - && requires(I Iter) { { Iter++ } -> CSameAs; }; - -template -concept CInputOrOutputIterator = CWeaklyIncrementable - && requires(I Iter) { { *Iter } -> CReferenceable; }; - -template -concept CSentinelFor = CSemiregular && CInputOrOutputIterator && CWeaklyEqualityComparable; - -template -inline constexpr bool bDisableSizedSentinelFor = false; - -template -concept CSizedSentinelFor = CSentinelFor && CPartiallyOrdered - && !bDisableSizedSentinelFor, TRemoveCV> - && requires(const I& Iter, const S& Sentinel) - { - { Sentinel - Iter } -> CSameAs; - { Iter - Sentinel } -> CSameAs; - }; - -template -concept CInputIterator = CInputOrOutputIterator && CIndirectlyReadable; - -template -concept COutputIterator = CInputOrOutputIterator && CIndirectlyWritable - && requires(I Iter, T&& A) { *Iter++ = Forward(A); }; - -template -concept CForwardIterator = CInputIterator && CIncrementable && CSentinelFor; - -template -concept CBidirectionalIterator = CForwardIterator - && requires(I Iter) { - { --Iter } -> CSameAs; - { Iter-- } -> CSameAs; - }; - -template -concept CRandomAccessIterator = CBidirectionalIterator && CTotallyOrdered && CSizedSentinelFor - && requires(I Iter, const I Jter, const ptrdiff N) { - { Iter += N } -> CSameAs; - { Jter + N } -> CSameAs; - { N + Jter } -> CSameAs; - { Iter -= N } -> CSameAs; - { Jter - N } -> CSameAs; - { Jter[N] } -> CSameAs>; - }; - -template -concept CContiguousIterator = CRandomAccessIterator && CLValueReference> - && CSameAs, TRemoveCVRef>> - && requires(I& Iter) - { - { ToAddress(Iter) } -> CSameAs>>; - }; - -static_assert(CContiguousIterator); +using TIteratorRValueReferenceType = TIteratorRValueReference; NAMESPACE_BEGIN(Iteration)