#pragma once #include "CoreTypes.h" #include "Range/Utility.h" #include "Templates/Utility.h" #include "TypeTraits/TypeTraits.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_BEGIN(Range) /** An interface class template for defining a view. Not directly instantiable. */ template requires (CSameAs>) class IBasicViewInterface { public: /** @return The pointer to the underlying element storage. */ NODISCARD FORCEINLINE constexpr auto GetData() requires (CContiguousRange< T>) { return Range::GetData(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr auto GetData() const requires (CContiguousRange) { return Range::GetData(static_cast(*this)); } /** @return The reverse iterator to the first or end element. */ NODISCARD FORCEINLINE constexpr auto Begin() requires (CRange< T>) { return Range::Begin(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr auto End() requires (CRange< T>) { return Range::End (static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr auto Begin() const requires (CRange) { return Range::Begin(static_cast(*this)); } NODISCARD FORCEINLINE constexpr auto End() const requires (CRange) { return Range::End (static_cast(*this)); } /** @return The reverse iterator to the first or end element. */ NODISCARD FORCEINLINE constexpr auto RBegin() requires (CBidirectionalRange< T> && CCommonRange< T>) { return Range::RBegin(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr auto REnd() requires (CBidirectionalRange< T> && CCommonRange< T>) { return Range::REnd (static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr auto RBegin() const requires (CBidirectionalRange && CCommonRange) { return Range::RBegin(static_cast(*this)); } NODISCARD FORCEINLINE constexpr auto REnd() const requires (CBidirectionalRange && CCommonRange) { return Range::REnd (static_cast(*this)); } /** @return The number of elements in the container. */ NODISCARD FORCEINLINE constexpr size_t Num() requires (CSizedRange< T>) { return Range::Num(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedRange) { return Range::Num(static_cast(*this)); } /** @return true if the container is empty, false otherwise. */ NODISCARD FORCEINLINE constexpr bool IsEmpty() requires (CSizedRange< T> || CForwardRange< T>) { return Range::IsEmpty(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr bool IsEmpty() const requires (CSizedRange || CForwardRange) { return Range::IsEmpty(static_cast(*this)); } /** @return true if the container is empty, false otherwise. */ NODISCARD FORCEINLINE constexpr explicit operator bool() requires (CSizedRange< T> || CForwardRange< T>) { return !Range::IsEmpty(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr explicit operator bool() const requires (CSizedRange || CForwardRange) { return !Range::IsEmpty(static_cast(*this)); } /** @return The reference to the requested element. */ NODISCARD FORCEINLINE constexpr decltype(auto) operator[](size_t Index) requires (CRandomAccessRange< T>) { return Range::Begin(static_cast< T&>(*this))[Index]; } NODISCARD FORCEINLINE constexpr decltype(auto) operator[](size_t Index) const requires (CRandomAccessRange) { return Range::Begin(static_cast(*this))[Index]; } /** @return The reference to the first or last element. */ NODISCARD FORCEINLINE constexpr decltype(auto) Front() requires (CForwardRange< T>) { return *Range::Begin(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr decltype(auto) Front() const requires (CForwardRange) { return *Range::Begin(static_cast(*this)); } NODISCARD FORCEINLINE constexpr decltype(auto) Back() requires (CBidirectionalRange< T> && CCommonRange< T>) { return *Range::RBegin(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr decltype(auto) Back() const requires (CBidirectionalRange && CCommonRange) { return *Range::RBegin(static_cast(*this)); } ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT private: FORCEINLINE constexpr IBasicViewInterface() = default; FORCEINLINE constexpr IBasicViewInterface(const IBasicViewInterface&) = default; FORCEINLINE constexpr IBasicViewInterface(IBasicViewInterface&&) = default; FORCEINLINE constexpr IBasicViewInterface& operator=(const IBasicViewInterface&) = default; FORCEINLINE constexpr IBasicViewInterface& operator=(IBasicViewInterface&&) = default; FORCEINLINE constexpr ~IBasicViewInterface() = default; friend T; }; NAMESPACE_END(Range) /** * A concept specifies that a range is a view, that is, it has constant time copy, move and assignment. * Specify, a view can be movable only but not copyable, or it can be both movable and copyable. */ template concept CView = CRange && CMovable && CDerivedFrom>>; NAMESPACE_PRIVATE_BEGIN template struct TIsInitializerList : FFalse { }; template struct TIsInitializerList> : FTrue { }; NAMESPACE_PRIVATE_END /** A concept specifies that a viewable range that can be converted into a view through Range::All. */ template concept CViewableRange = CRange && ((CView> && CConstructibleFrom, R>) || (!CView> && (CLValueReference || (CMovable> && !NAMESPACE_PRIVATE::TIsInitializerList>::Value)))); NAMESPACE_BEGIN(Range) /** A simple view that combines an iterator-sentinel pair into a view. */ template S = I> class TRangeView : public IBasicViewInterface> { public: using FElementType = TIteratorElementType; FORCEINLINE constexpr TRangeView() requires (CDefaultConstructible) = default; FORCEINLINE constexpr TRangeView(I InFirst, S InLast) : First(MoveTemp(InFirst)), Last(InLast) { } NODISCARD FORCEINLINE constexpr I Begin() requires (!CCopyable) { return MoveTemp(First); } NODISCARD FORCEINLINE constexpr I Begin() const requires ( CCopyable) { return First; } NODISCARD FORCEINLINE constexpr S End() const { return Last; } NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedSentinelFor) { return Last - First; } NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return First == Last; } private: NO_UNIQUE_ADDRESS I First; NO_UNIQUE_ADDRESS S Last; }; template S> TRangeView(I, S) -> TRangeView; NAMESPACE_END(Range) template constexpr bool bEnableBorrowedRange> = true; NAMESPACE_BEGIN(Range) /** Creates A simple view that combines an iterator-sentinel pair. */ template S = I> NODISCARD FORCEINLINE constexpr TRangeView View(I First, S Last) { return TRangeView(MoveTemp(First), Last); } NAMESPACE_END(Range) NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END