#pragma once #include "CoreTypes.h" #include "Templates/Meta.h" #include "Templates/Invoke.h" #include "Templates/Utility.h" #include "Templates/TypeHash.h" #include "TypeTraits/TypeTraits.h" #include "Templates/ReferenceWrapper.h" #include NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) #define RS_TUPLE_ELEMENT_STATIC_ALIAS 1 template class TTuple; NAMESPACE_PRIVATE_BEGIN template struct TIsTTuple : FFalse { }; template struct TIsTTuple> : FTrue { }; struct FForwardingConstructor { explicit FForwardingConstructor() = default; }; struct FOtherTupleConstructor { explicit FOtherTupleConstructor() = default; }; inline constexpr FForwardingConstructor ForwardingConstructor{ }; inline constexpr FOtherTupleConstructor OtherTupleConstructor{ }; template struct TTupleArityImpl; template struct TTupleArityImpl> : TConstant>> { }; template struct TTupleIndexImpl; template struct TTupleIndexImpl> : TConstant>> { }; template struct TTupleElementImpl; template struct TTupleElementImpl> { using Type = Meta::TType>; }; template struct TTupleConvertCopy : FTrue { }; template struct TTupleConvertCopy : TBoolConstant&, T> || CConstructibleFrom&> || CSameAs)> { }; template struct TTupleConvertMove : FTrue { }; template struct TTupleConvertMove : TBoolConstant&&, T> || CConstructibleFrom&&> || CSameAs)> { }; template struct TTupleBasicElement { private: using ValueType = T; ValueType Value; public: template FORCEINLINE constexpr TTupleBasicElement(Type&& Arg) : Value(Forward(Arg)) { } FORCEINLINE constexpr TTupleBasicElement() = default; FORCEINLINE constexpr TTupleBasicElement(const TTupleBasicElement&) = default; FORCEINLINE constexpr TTupleBasicElement(TTupleBasicElement&&) = default; FORCEINLINE constexpr TTupleBasicElement& operator=(const TTupleBasicElement&) = default; FORCEINLINE constexpr TTupleBasicElement& operator=(TTupleBasicElement&&) = default; FORCEINLINE constexpr ~TTupleBasicElement() = default; FORCEINLINE constexpr T& GetValue() & { return static_cast< T& >(Value); } FORCEINLINE constexpr const T& GetValue() const & { return static_cast(Value); } FORCEINLINE constexpr volatile T& GetValue() volatile& { return static_cast< volatile T& >(Value); } FORCEINLINE constexpr const volatile T& GetValue() const volatile& { return static_cast(Value); } FORCEINLINE constexpr T&& GetValue() && { return static_cast< T&&>(Value); } FORCEINLINE constexpr const T&& GetValue() const && { return static_cast(Value); } FORCEINLINE constexpr volatile T&& GetValue() volatile&& { return static_cast< volatile T&&>(Value); } FORCEINLINE constexpr const volatile T&& GetValue() const volatile&& { return static_cast(Value); } }; #if RS_TUPLE_ELEMENT_STATIC_ALIAS #define DEFINE_TTupleBasicElement(Index, Name) \ template \ struct TTupleBasicElement \ { \ using Name##Type = T; \ Name##Type Name; \ \ template \ FORCEINLINE constexpr TTupleBasicElement(Type&& Arg) \ : Name(Forward(Arg)) \ { } \ \ FORCEINLINE constexpr TTupleBasicElement() = default; \ FORCEINLINE constexpr TTupleBasicElement(const TTupleBasicElement&) = default; \ FORCEINLINE constexpr TTupleBasicElement(TTupleBasicElement&&) = default; \ FORCEINLINE constexpr TTupleBasicElement& operator=(const TTupleBasicElement&) = default; \ FORCEINLINE constexpr TTupleBasicElement& operator=(TTupleBasicElement&&) = default; \ FORCEINLINE constexpr ~TTupleBasicElement() = default; \ \ FORCEINLINE constexpr T& GetValue() & { return static_cast< T& >(Name); } \ FORCEINLINE constexpr const T& GetValue() const & { return static_cast(Name); } \ FORCEINLINE constexpr volatile T& GetValue() volatile& { return static_cast< volatile T& >(Name); } \ FORCEINLINE constexpr const volatile T& GetValue() const volatile& { return static_cast(Name); } \ FORCEINLINE constexpr T&& GetValue() && { return static_cast< T&&>(Name); } \ FORCEINLINE constexpr const T&& GetValue() const && { return static_cast(Name); } \ FORCEINLINE constexpr volatile T&& GetValue() volatile&& { return static_cast< volatile T&&>(Name); } \ FORCEINLINE constexpr const volatile T&& GetValue() const volatile&& { return static_cast(Name); } \ } DEFINE_TTupleBasicElement(0x0, First); DEFINE_TTupleBasicElement(0x1, Second); DEFINE_TTupleBasicElement(0x2, Third); DEFINE_TTupleBasicElement(0x3, Fourth); DEFINE_TTupleBasicElement(0x4, Fifth); DEFINE_TTupleBasicElement(0x5, Sixth); DEFINE_TTupleBasicElement(0x6, Seventh); DEFINE_TTupleBasicElement(0x7, Eighth); DEFINE_TTupleBasicElement(0x8, Ninth); DEFINE_TTupleBasicElement(0x9, Tenth); DEFINE_TTupleBasicElement(0xA, Eleventh); DEFINE_TTupleBasicElement(0xB, Twelfth); DEFINE_TTupleBasicElement(0xC, Thirteenth); DEFINE_TTupleBasicElement(0xD, Fourteenth); DEFINE_TTupleBasicElement(0xE, Fifteenth); DEFINE_TTupleBasicElement(0xF, Sixteenth); #undef DEFINE_TTupleBasicElement #endif template FORCEINLINE constexpr TTuple...> MakeTupleImpl(Ts&&... Args) { return TTuple...>(Forward(Args)...); } template class TTupleImpl; template class TTupleImpl, Ts...> : public TTupleBasicElement... { protected: FORCEINLINE constexpr TTupleImpl() = default; FORCEINLINE constexpr TTupleImpl(const TTupleImpl&) = default; FORCEINLINE constexpr TTupleImpl(TTupleImpl&&) = default; FORCEINLINE constexpr TTupleImpl& operator=(const TTupleImpl&) = default; FORCEINLINE constexpr TTupleImpl& operator=(TTupleImpl&&) = default; FORCEINLINE constexpr ~TTupleImpl() = default; template FORCEINLINE constexpr explicit TTupleImpl(FForwardingConstructor, ArgTypes&&... Args) : TTupleBasicElement(Forward(Args))... { } template FORCEINLINE constexpr explicit TTupleImpl(FOtherTupleConstructor, TupleType&& InValue) : TTupleBasicElement(Forward(InValue).template GetValue())... { } }; template class TTupleHelper; template class TTupleHelper> { public: template FORCEINLINE static constexpr void Assign(LHSTupleType& LHS, RHSTupleType&& RHS) { static_assert(sizeof...(Indices) == TTupleArityImpl>::Value && TTupleArityImpl>::Value == TTupleArityImpl>::Value, "Cannot assign tuple from different size"); ((LHS.template GetValue() = Forward(RHS).template GetValue()), ...); } template FORCEINLINE static constexpr auto Apply(F&& Func, TTupleType&& Arg) { return Invoke(Forward(Func), Forward(Arg).template GetValue()...); } template FORCEINLINE static constexpr auto Transform(F&& Func, TTupleType&& Arg) { return MakeTupleImpl(Invoke(Forward(Func), Forward(Arg).template GetValue())...); } template FORCEINLINE static constexpr T Construct(TTupleType&& Arg) { return T(Forward(Arg).template GetValue()...); } }; template struct TTupleThreeWay; template struct TTupleThreeWay> { template FORCEINLINE static constexpr R Do(const LHSTupleType& LHS, const RHSTupleType& RHS) { auto Result = SynthThreeWayCompare(LHS.template GetValue(), RHS.template GetValue()); if (Result != 0) return Result; return TTupleThreeWay>::Do(LHS, RHS); } }; template struct TTupleThreeWay> { template FORCEINLINE static constexpr R Do(const LHSTupleType& LHS, const RHSTupleType& RHS) { return R::equivalent; } }; template struct TTTupleWeaklyEqualityComparable; template struct TTTupleWeaklyEqualityComparable, TTypeSequence> : TBoolConstant && TTTupleWeaklyEqualityComparable, TTypeSequence>::Value> { }; template <> struct TTTupleWeaklyEqualityComparable, TTypeSequence<>> : FTrue { }; template concept CTTupleWeaklyEqualityComparable = TTTupleWeaklyEqualityComparable::Value; template struct TTTupleSynthThreeWayComparable; template struct TTTupleSynthThreeWayComparable, TTypeSequence> : TBoolConstant && TTTupleSynthThreeWayComparable, TTypeSequence>::Value> { }; template <> struct TTTupleSynthThreeWayComparable, TTypeSequence<>> : FTrue { }; template concept CTTupleSynthThreeWayComparable = TTTupleSynthThreeWayComparable::Value; NAMESPACE_PRIVATE_END template concept CTTuple = NAMESPACE_PRIVATE::TIsTTuple>::Value; template inline constexpr size_t TTupleArity = NAMESPACE_PRIVATE::TTupleArityImpl>::Value; template inline constexpr size_t TTupleIndex = NAMESPACE_PRIVATE::TTupleIndexImpl>::Value; template using TTupleElement = TCopyCV>::Type>; template class TTuple : public NAMESPACE_PRIVATE::TTupleImpl, Ts...> { private: using Super = NAMESPACE_PRIVATE::TTupleImpl, Ts...>; using Helper = NAMESPACE_PRIVATE::TTupleHelper>; public: FORCEINLINE constexpr TTuple() = default; template requires (sizeof...(Ts) >= 1 && sizeof...(ArgTypes) == sizeof...(Ts)) && (true && ... && CConstructibleFrom) FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo)) TTuple(ArgTypes&&... Args) : Super(NAMESPACE_PRIVATE::ForwardingConstructor, Forward(Args)...) { } template requires (sizeof...(Us) == sizeof...(Ts) && (true && ... && CConstructibleFrom) && NAMESPACE_PRIVATE::TTupleConvertCopy::Value) FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo)) TTuple(const TTuple& InValue) : Super(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue) { } template requires (sizeof...(Us) == sizeof...(Ts) && (true && ... && CConstructibleFrom) && NAMESPACE_PRIVATE::TTupleConvertMove::Value) FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo)) TTuple(TTuple&& InValue) : Super(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue)) { } FORCEINLINE constexpr TTuple(const TTuple&) = default; FORCEINLINE constexpr TTuple(TTuple&&) = default; template requires (sizeof...(Us) == sizeof...(Ts) && (true && ... && CAssignableFrom)) FORCEINLINE constexpr TTuple& operator=(const TTuple& InValue) { Helper::Assign(*this, InValue); return *this; } template requires (sizeof...(Us) == sizeof...(Ts) && (true && ... && CAssignableFrom)) FORCEINLINE constexpr TTuple& operator=(TTuple&& InValue) { Helper::Assign(*this, MoveTemp(InValue)); return *this; } FORCEINLINE constexpr TTuple& operator=(const TTuple&) = default; FORCEINLINE constexpr TTuple& operator=(TTuple&&) = default; template requires (sizeof...(Ts) == sizeof...(Us) && NAMESPACE_PRIVATE::CTTupleWeaklyEqualityComparable, TTypeSequence>) friend FORCEINLINE constexpr bool operator==(const TTuple& LHS, const TTuple& RHS) { if constexpr (sizeof...(Ts) != sizeof...(Us)) return false; return [&LHS, &RHS](TIndexSequence) -> bool { return (true && ... && (LHS.template GetValue() == RHS.template GetValue())); } (TMakeIndexSequence()); } template requires (sizeof...(Ts) == sizeof...(Us) && NAMESPACE_PRIVATE::CTTupleSynthThreeWayComparable, TTypeSequence>) friend FORCEINLINE constexpr TCommonComparisonCategory...> operator<=>(const TTuple& LHS, const TTuple& RHS) { using R = TCommonComparisonCategory...>; return NAMESPACE_PRIVATE::TTupleThreeWay>::Do(LHS, RHS); } template requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() & { return static_cast< NAMESPACE_PRIVATE::TTupleBasicElement>, I>& >(*this).GetValue(); } template requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() const & { return static_cast>, I>& >(*this).GetValue(); } template requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() volatile& { return static_cast< volatile NAMESPACE_PRIVATE::TTupleBasicElement>, I>& >(*this).GetValue(); } template requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() const volatile& { return static_cast>, I>& >(*this).GetValue(); } template requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() && { return static_cast< NAMESPACE_PRIVATE::TTupleBasicElement>, I>&&>(*this).GetValue(); } template requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() const && { return static_cast>, I>&&>(*this).GetValue(); } template requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() volatile&& { return static_cast< volatile NAMESPACE_PRIVATE::TTupleBasicElement>, I>&&>(*this).GetValue(); } template requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() const volatile&& { return static_cast>, I>&&>(*this).GetValue(); } template FORCEINLINE constexpr decltype(auto) GetValue() & { return static_cast< TTuple& >(*this).GetValue>>(); } template FORCEINLINE constexpr decltype(auto) GetValue() const & { return static_cast(*this).GetValue>>(); } template FORCEINLINE constexpr decltype(auto) GetValue() volatile& { return static_cast< volatile TTuple& >(*this).GetValue>>(); } template FORCEINLINE constexpr decltype(auto) GetValue() const volatile& { return static_cast(*this).GetValue>>(); } template FORCEINLINE constexpr decltype(auto) GetValue() && { return static_cast< TTuple&&>(*this).GetValue>>(); } template FORCEINLINE constexpr decltype(auto) GetValue() const && { return static_cast(*this).GetValue>>(); } template FORCEINLINE constexpr decltype(auto) GetValue() volatile&& { return static_cast< volatile TTuple&&>(*this).GetValue>>(); } template FORCEINLINE constexpr decltype(auto) GetValue() const volatile&& { return static_cast(*this).GetValue>>(); } template requires (CInvocable) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) & { return Helper::Apply(Forward(Func), static_cast< TTuple& >(*this)); } template requires (CInvocable) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const & { return Helper::Apply(Forward(Func), static_cast(*this)); } template requires (CInvocable) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile& { return Helper::Apply(Forward(Func), static_cast< volatile TTuple& >(*this)); } template requires (CInvocable) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile& { return Helper::Apply(Forward(Func), static_cast(*this)); } template requires (CInvocable) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) && { return Helper::Apply(Forward(Func), static_cast< TTuple&&>(*this)); } template requires (CInvocable) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const && { return Helper::Apply(Forward(Func), static_cast(*this)); } template requires (CInvocable) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) volatile&& { return Helper::Apply(Forward(Func), static_cast< volatile TTuple&&>(*this)); } template requires (CInvocable) FORCEINLINE constexpr decltype(auto) Apply(F&& Func) const volatile&& { return Helper::Apply(Forward(Func), static_cast(*this)); } template requires (true && ... && (CInvocable && !CSameAs>)) FORCEINLINE constexpr decltype(auto) Transform(F&& Func) & { return Helper::Transform(Forward(Func), static_cast< TTuple& >(*this)); } template requires (true && ... && (CInvocable && !CSameAs>)) FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const & { return Helper::Transform(Forward(Func), static_cast(*this)); } template requires (true && ... && (CInvocable && !CSameAs>)) FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile& { return Helper::Transform(Forward(Func), static_cast< volatile TTuple& >(*this)); } template requires (true && ... && (CInvocable && !CSameAs>)) FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile& { return Helper::Transform(Forward(Func), static_cast(*this)); } template requires (true && ... && (CInvocable && !CSameAs>)) FORCEINLINE constexpr decltype(auto) Transform(F&& Func) && { return Helper::Transform(Forward(Func), static_cast< TTuple&&>(*this)); } template requires (true && ... && (CInvocable && !CSameAs>)) FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const && { return Helper::Transform(Forward(Func), static_cast(*this)); } template requires (true && ... && (CInvocable && !CSameAs>)) FORCEINLINE constexpr decltype(auto) Transform(F&& Func) volatile&& { return Helper::Transform(Forward(Func), static_cast< volatile TTuple&&>(*this)); } template requires (true && ... && (CInvocable && !CSameAs>)) FORCEINLINE constexpr decltype(auto) Transform(F&& Func) const volatile&& { return Helper::Transform(Forward(Func), static_cast(*this)); } template requires (CConstructibleFrom) FORCEINLINE constexpr T Construct() & { return Helper::template Construct(static_cast< TTuple& >(*this)); } template requires (CConstructibleFrom) FORCEINLINE constexpr T Construct() const & { return Helper::template Construct(static_cast(*this)); } template requires (CConstructibleFrom) FORCEINLINE constexpr T Construct() volatile& { return Helper::template Construct(static_cast< volatile TTuple& >(*this)); } template requires (CConstructibleFrom) FORCEINLINE constexpr T Construct() const volatile& { return Helper::template Construct(static_cast(*this)); } template requires (CConstructibleFrom) FORCEINLINE constexpr T Construct() && { return Helper::template Construct(static_cast< TTuple&&>(*this)); } template requires (CConstructibleFrom) FORCEINLINE constexpr T Construct() const && { return Helper::template Construct(static_cast(*this)); } template requires (CConstructibleFrom) FORCEINLINE constexpr T Construct() volatile&& { return Helper::template Construct(static_cast< volatile TTuple&&>(*this)); } template requires (CConstructibleFrom) FORCEINLINE constexpr T Construct() const volatile&& { return Helper::template Construct(static_cast(*this)); } FORCEINLINE constexpr size_t GetTypeHash() const requires (true && ... && CHashable) { return [this](TIndexSequence) -> size_t { return HashCombine(NAMESPACE_REDCRAFT::GetTypeHash(GetValue())...); } (TMakeIndexSequence()); } FORCEINLINE constexpr void Swap(TTuple& InValue) requires (true && ... && (CMoveConstructible && CSwappable)) { [&A = *this, &B = InValue](TIndexSequence) { ((NAMESPACE_REDCRAFT::Swap(A.template GetValue(), B.template GetValue())), ...); } (TMakeIndexSequence()); } }; template TTuple(Ts...) -> TTuple; template using TPair = TTuple; template FORCEINLINE constexpr TTuple...> MakeTuple(Ts&&... Args) { return TTuple...>(Forward(Args)...); } template FORCEINLINE constexpr TTuple Tie(Ts&... Args) { return TTuple(Args...); } template FORCEINLINE constexpr TTuple ForwardAsTuple(Ts&&... Args) { return TTuple(Forward(Args)...); } NAMESPACE_PRIVATE_BEGIN struct FTupleEndFlag { }; template struct TTupleCatResultImpl; template struct TTupleCatResultImpl, TTupleTypes...> { using Type = typename TTupleCatResultImpl::Type; }; template struct TTupleCatResultImpl { using Type = TTuple; }; template struct TTupleCatMake; template struct TTupleCatMake, TIndexSequence> { template struct ForwardType { using Type = TConditional, TRemoveReference&&, U>; }; template FORCEINLINE static constexpr TTuple Do(TTupleType&& InValue) { return TTuple ( static_cast(InValue).template GetValue())>::Type> ( Forward(InValue).template GetValue() )... ); } }; template struct TTupleCatForward; template struct TTupleCatForward, TIndexSequence> { template FORCEINLINE static constexpr decltype(auto) Do(ForwardType&& ForwardTuple, TTupleType&& InValue) { return ForwardAsTuple(Forward(ForwardTuple).template GetValue()..., Forward(InValue).template GetValue()...); } }; template struct TTupleCatImpl { template FORCEINLINE static constexpr decltype(auto) Do(ForwardType&& ForwardTuple, TTupleType&& InValue, OtherTTupleTypes&&... OtherValue) { return Do(TTupleCatForward< TMakeIndexSequence>>, TMakeIndexSequence>>> ::Do(Forward(ForwardTuple), Forward(InValue)), Forward(OtherValue)...); } template FORCEINLINE static constexpr decltype(auto) Do(ForwardType&& ForwardTuple) { return TTupleCatMake>>::Do(Forward(ForwardTuple)); } }; template struct TTupleVisitImpl; template struct TTupleVisitImpl> { template FORCEINLINE static constexpr void Do(F&& Func, TupleTypes&&... Tuples) { Invoke(Forward(Func), Forward(Tuples).template GetValue()...); TTupleVisitImpl>::Do(Forward(Func), Forward(Tuples)...); } }; template <> struct TTupleVisitImpl> { template FORCEINLINE static constexpr void Do(TupleTypes&&... Tuples) { } }; NAMESPACE_PRIVATE_END template requires (true && ... && CTTuple>) using TTupleCatResult = typename NAMESPACE_PRIVATE::TTupleCatResultImpl..., NAMESPACE_PRIVATE::FTupleEndFlag>::Type;; template requires (true && ... && CTTuple>) FORCEINLINE constexpr decltype(auto) TupleCat(TTupleTypes&&... Args) { using R = TTupleCatResult; if constexpr (sizeof...(Args) == 0) return R(); else return NAMESPACE_PRIVATE::TTupleCatImpl::Do(Forward(Args)...); } template requires (CTTuple> && (true && ... && CTTuple>)) FORCEINLINE constexpr void VisitTuple(F&& Func, FirstTupleType&& FirstTuple, TupleTypes&&... Tuples) { NAMESPACE_PRIVATE::TTupleVisitImpl>>> ::Do(Forward(Func), Forward(FirstTuple), Forward(Tuples)...); } template requires (requires { typename TTuple...>; }) struct TBasicCommonType, TTuple> { using Type = TTuple...>; }; template typename TQualifiers, template typename UQualifiers> requires (requires { typename TTuple, UQualifiers>...>; }) struct TBasicCommonReference, TTuple, TQualifiers, UQualifiers> { using Type = TTuple, UQualifiers>...>; }; NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END NAMESPACE_STD_BEGIN // Support structure binding, should not be directly used template struct tuple_size> : integral_constant>> { }; template struct tuple_element> { using type = NAMESPACE_REDCRAFT::TTupleElement>; }; NAMESPACE_STD_END NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) // Support structure binding, should not be directly used template FORCEINLINE constexpr decltype(auto) get( TTuple& InValue) { return static_cast< TTuple& >(InValue).template GetValue(); } template FORCEINLINE constexpr decltype(auto) get(const TTuple& InValue) { return static_cast& >(InValue).template GetValue(); } template FORCEINLINE constexpr decltype(auto) get( volatile TTuple& InValue) { return static_cast< volatile TTuple& >(InValue).template GetValue(); } template FORCEINLINE constexpr decltype(auto) get(const volatile TTuple& InValue) { return static_cast& >(InValue).template GetValue(); } template FORCEINLINE constexpr decltype(auto) get( TTuple&& InValue) { return static_cast< TTuple&&>(InValue).template GetValue(); } template FORCEINLINE constexpr decltype(auto) get(const TTuple&& InValue) { return static_cast&&>(InValue).template GetValue(); } template FORCEINLINE constexpr decltype(auto) get( volatile TTuple&& InValue) { return static_cast< volatile TTuple&&>(InValue).template GetValue(); } template FORCEINLINE constexpr decltype(auto) get(const volatile TTuple&& InValue) { return static_cast&&>(InValue).template GetValue(); } NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END