#pragma once #include "CoreTypes.h" #include "Ranges/Utility.h" #include "Templates/Tuple.h" #include "Templates/Invoke.h" #include "Templates/Utility.h" #include "TypeTraits/TypeTraits.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_BEGIN(Ranges) /** * An interface class template for defining a range adaptor closure. * When the derived class has a unary operator() with range as a reference and is not itself a range, * the derived class is the range adaptor closure type and its objects can participate in pipe operations. * Specify, the unary operator() with any reference qualifier or cv-qualifier must be defined and has same effect. * Not directly instantiable. */ template requires (CSameAs>) class IAdaptorClosure { }; /** An adaptor closure helper that wraps a callable object. */ template requires (CEmpty && ... && CSameAs, Ts>) class TAdaptorClosure : public IAdaptorClosure> { public: template requires (CConstructibleFrom, Us...> && ... && CSameAs, Ts>) FORCEINLINE constexpr explicit TAdaptorClosure(Us&&... InArgs) : Args(Forward(InArgs)...) { } template requires (CInvocable) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) & { return [this, &Range](TIndexSequence) { return Invoke(F(), Forward(Range), Args.template GetValue()...); } (TMakeIndexSequence()); } template requires (CInvocable) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const& { return [this, &Range](TIndexSequence) { return Invoke(F(), Forward(Range), Args.template GetValue()...); } (TMakeIndexSequence()); } template requires (CInvocable) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) && { return [this, &Range](TIndexSequence) { return Invoke(F(), Forward(Range), MoveTemp(Args).template GetValue()...); } (TMakeIndexSequence()); } template requires (CInvocable) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&& { return [this, &Range](TIndexSequence) { return Invoke(F(), Forward(Range), MoveTemp(Args).template GetValue()...); } (TMakeIndexSequence()); } private: NO_UNIQUE_ADDRESS TTuple Args; }; /** A pipe closure that wraps two adaptor closures. */ template requires (CSameAs, T> && CDerivedFrom> && CSameAs, U> && CDerivedFrom>) class TPipeClosure final : public IAdaptorClosure> { public: template requires (CSameAs, T> && CConstructibleFrom && CSameAs, U> && CConstructibleFrom) FORCEINLINE constexpr explicit TPipeClosure(V InLHS, W InRHS) : LHS(Forward(InLHS)), RHS(Forward(InRHS)) { } template requires (CInvocable && CInvocable>) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) & { return Forward(Range) | LHS | RHS; } template requires (CInvocable && CInvocable>) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const& { return Forward(Range) | LHS | RHS; } template requires (CInvocable && CInvocable>) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) && { return Forward(Range) | MoveTemp(LHS) | MoveTemp(RHS); } template requires (CInvocable && CInvocable>) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&& { return Forward(Range) | MoveTemp(LHS) | MoveTemp(RHS); } private: NO_UNIQUE_ADDRESS T LHS; NO_UNIQUE_ADDRESS U RHS; }; /** Apply the range adaptor closure to the range. */ template T> requires (CDerivedFrom, IAdaptorClosure>>) NODISCARD FORCEINLINE constexpr auto operator|(R&& Range, T&& Closure) { return Invoke(Forward(Closure), Forward(Range)); } /** Create a pipe closure that wraps two adaptor closures. */ template requires (CDerivedFrom, IAdaptorClosure>> && CDerivedFrom, IAdaptorClosure>>) NODISCARD FORCEINLINE constexpr auto operator|(T&& LHS, U&& RHS) { return TPipeClosure, TRemoveCVRef>(Forward(LHS), Forward(RHS)); } NAMESPACE_END(Ranges) NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END