#pragma once #include "CoreTypes.h" #include "Range/Utility.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(Range) /** * 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 class TAdaptorClosure : public IAdaptorClosure> { public: FORCEINLINE constexpr explicit TAdaptorClosure(F InClosure) : Closure(MoveTemp(InClosure)) { } template requires (CInvocable) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) & { return Invoke(Closure, Forward(Range)); } template requires (CInvocable) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const& { return Invoke(Closure, Forward(Range)); } template requires (CInvocable) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) && { return Invoke(MoveTemp(Closure), Forward(Range)); } template requires (CInvocable) NODISCARD FORCEINLINE constexpr auto operator()(R&& Range) const&& { return Invoke(MoveTemp(Closure), Forward(Range)); } private: NO_UNIQUE_ADDRESS F Closure; }; /** A pipe closure that wraps two adaptor closures. */ template requires (CDerivedFrom> && CDerivedFrom>) class TPipeClosure final : public IAdaptorClosure> { public: FORCEINLINE constexpr explicit TPipeClosure(T InLHS, U InRHS) : LHS(MoveTemp(InLHS)), RHS(MoveTemp(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> && CDerivedFrom>) NODISCARD FORCEINLINE constexpr auto operator|(T LHS, U RHS) { return TPipeClosure(MoveTemp(LHS), MoveTemp(RHS)); } NAMESPACE_END(Range) NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END