From f1d4d99ecf3cb214718c15c0177f88842af79ef8 Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Thu, 16 Jun 2022 23:37:29 +0800 Subject: [PATCH] refactor(*): replaces template class type traits with C++20 at all --- .../Private/Testing/MiscellaneousTesting.cpp | 16 +- .../Private/Testing/TemplatesTesting.cpp | 74 ++- .../Private/Testing/TypeTraitsTesting.cpp | 12 +- .../Source/Public/Miscellaneous/Compare.h | 35 +- .../Source/Public/Templates/Any.h | 3 +- .../Source/Public/Templates/IntegerSequence.h | 12 +- .../Source/Public/Templates/Optional.h | 6 +- .../Public/Templates/ReferenceWrapper.h | 24 +- .../Source/Public/Templates/Tuple.h | 435 ++++++++++-------- .../Source/Public/Templates/Variant.h | 179 ++++--- .../Source/Public/TypeTraits/Miscellaneous.h | 4 +- 11 files changed, 438 insertions(+), 362 deletions(-) diff --git a/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp b/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp index ab250fd..6d8d9de 100644 --- a/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp @@ -188,9 +188,9 @@ void TestCompare() always_check((FTestStrongOrdering( 0) == FTestStrongOrdering( 0))); always_check((FTestStrongOrdering( 0) > FTestStrongOrdering(-1))); - always_check((CSameAs::Type, strong_ordering >)); - always_check((CSameAs::Type, weak_ordering >)); - always_check((CSameAs::Type, partial_ordering>)); + always_check((CSameAs, strong_ordering >)); + always_check((CSameAs, weak_ordering >)); + always_check((CSameAs, partial_ordering>)); always_check(CThreeWayComparable); always_check(CThreeWayComparable); @@ -200,11 +200,11 @@ void TestCompare() always_check((CThreeWayComparable)); always_check((CThreeWayComparable)); - always_check((CSameAs::Type, strong_ordering >)); - always_check((CSameAs::Type, partial_ordering>)); - always_check((CSameAs::Type, partial_ordering>)); - always_check((CSameAs::Type, weak_ordering >)); - always_check((CSameAs::Type, strong_ordering >)); + always_check((CSameAs, strong_ordering >)); + always_check((CSameAs, partial_ordering>)); + always_check((CSameAs, partial_ordering>)); + always_check((CSameAs, weak_ordering >)); + always_check((CSameAs, strong_ordering >)); always_check((SynthThreeWayCompare(0, 0) == strong_ordering::equal)); always_check((SynthThreeWayCompare(0, 0.0) == strong_ordering::equal)); diff --git a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp index ad09e56..679a6e0 100644 --- a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp @@ -79,8 +79,8 @@ void TestReferenceWrapper() always_check(ArrayA[1] == 4); always_check(ArrayA[2] == 6); - always_check((CSameAs::Type>)); - always_check((CSameAs>::Type>)); + always_check((CSameAs>)); + always_check((CSameAs>>)); } void TestOptional() @@ -255,12 +255,12 @@ void TestVariant() TempZ = TVariant(); TempZ = FTracker(); - always_check((CSameAs>::Type>)); - always_check((CSameAs>::Type>)); - always_check((CSameAs>::Type>)); + always_check((CSameAs>>)); + always_check((CSameAs>>)); + always_check((CSameAs>>)); - always_check((TVariantAlternativeIndex>::Value == 0)); - always_check((TVariantAlternativeIndex>::Value == 1)); + always_check((TVariantIndex> == 0)); + always_check((TVariantIndex> == 1)); bool bIsConst; bool bIsLValue; @@ -686,39 +686,37 @@ void TestTuple() always_check((CSameAs&&>().GetValue<0>()), volatile int32&&>)); always_check((CSameAs&&>().GetValue<0>()), const volatile int32&&>)); - always_check((CSameAs>::Type, double>)); - always_check((CSameAs>::Type, float&>)); - always_check((CSameAs>::Type, char&&>)); - always_check((CSameAs>::Type, const double>)); - always_check((CSameAs>::Type, const float&>)); - always_check((CSameAs>::Type, const char&&>)); - always_check((CSameAs>::Type, volatile double>)); - always_check((CSameAs>::Type, volatile float&>)); - always_check((CSameAs>::Type, volatile char&&>)); - always_check((CSameAs>::Type, const volatile double>)); - always_check((CSameAs>::Type, const volatile float&>)); - always_check((CSameAs>::Type, const volatile char&&>)); + always_check((CSameAs>, double>)); + always_check((CSameAs>, float&>)); + always_check((CSameAs>, char&&>)); + always_check((CSameAs>, const double>)); + always_check((CSameAs>, float&>)); + always_check((CSameAs>, char&&>)); + always_check((CSameAs>, volatile double>)); + always_check((CSameAs>, float&>)); + always_check((CSameAs>, char&&>)); + always_check((CSameAs>, const volatile double>)); + always_check((CSameAs>, float&>)); + always_check((CSameAs>, char&&>)); - always_check((TTupleElementIndex>::Value == 0)); - always_check((TTupleElementIndex>::Value == 1)); - always_check((TTupleElementIndex>::Value == 2)); - always_check((TTupleElementIndex>::Value == 0)); - always_check((TTupleElementIndex>::Value == 1)); - always_check((TTupleElementIndex>::Value == 2)); - always_check((TTupleElementIndex>::Value == 0)); - always_check((TTupleElementIndex>::Value == 1)); - always_check((TTupleElementIndex>::Value == 2)); - always_check((TTupleElementIndex>::Value == 0)); - always_check((TTupleElementIndex>::Value == 1)); - always_check((TTupleElementIndex>::Value == 2)); + always_check((TTupleIndex> == 0)); + always_check((TTupleIndex> == 1)); + always_check((TTupleIndex> == 2)); + always_check((TTupleIndex> == 0)); + always_check((TTupleIndex> == 1)); + always_check((TTupleIndex> == 2)); + always_check((TTupleIndex> == 0)); + always_check((TTupleIndex> == 1)); + always_check((TTupleIndex> == 2)); + always_check((TTupleIndex> == 0)); + always_check((TTupleIndex> == 1)); + always_check((TTupleIndex> == 2)); - always_check((TTupleElementIndex>::Value == INDEX_NONE)); +// always_check((CSameAs, double>)); -// always_check((CSameAs::Type, double>)); +// always_check((TTupleIndex == 0)); -// always_check((TTupleElementIndex::Value == 0)); - -// always_check((CSameAs>::Type, double>)); +// always_check((CSameAs>, double>)); { using Type = TTuple() == 3.14); always_check(TempE.GetValue() == 1.42f); always_check((CSameAs>)); - always_check((CSameAs, TTuple, TTuple>::Type>)); + always_check((CSameAs, TTuple, TTuple>>)); } { @@ -827,7 +825,7 @@ void TestTuple() always_check(TempG.GetValue<0>() == 10); always_check(TempG.GetValue<2>() == 10); always_check((CSameAs>)); - always_check((CSameAs, TTuple>::Type>)); + always_check((CSameAs, TTuple>>)); } { diff --git a/Redcraft.Utility/Source/Private/Testing/TypeTraitsTesting.cpp b/Redcraft.Utility/Source/Private/Testing/TypeTraitsTesting.cpp index 1073c37..bef5256 100644 --- a/Redcraft.Utility/Source/Private/Testing/TypeTraitsTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/TypeTraitsTesting.cpp @@ -301,13 +301,13 @@ void TestTypeTraits() // Miscellaneous.h - always_check(ArrayRank == 3); - always_check(ArrayRank == 4); - always_check(ArrayRank == 0); + always_check(TRank == 3); + always_check(TRank == 4); + always_check(TRank == 0); - always_check(ArrayExtent == 1); - always_check((ArrayExtent == 2)); - always_check(ArrayExtent == 0); + always_check(TExtent == 1); + always_check((TExtent == 2)); + always_check(TExtent == 0); always_check(!(CSameAs)); always_check((CSameAs)); diff --git a/Redcraft.Utility/Source/Public/Miscellaneous/Compare.h b/Redcraft.Utility/Source/Public/Miscellaneous/Compare.h index 05b1bbb..d7d9326 100644 --- a/Redcraft.Utility/Source/Public/Miscellaneous/Compare.h +++ b/Redcraft.Utility/Source/Public/Miscellaneous/Compare.h @@ -18,17 +18,15 @@ typedef NAMESPACE_STD::strong_ordering strong_ordering; NAMESPACE_PRIVATE_BEGIN -template struct TCommonComparisonCategory { using Type = void; }; -template<> struct TCommonComparisonCategory<0> { using Type = strong_ordering; }; -template<> struct TCommonComparisonCategory<2> { using Type = partial_ordering; }; -template<> struct TCommonComparisonCategory<4> { using Type = weak_ordering; }; -template<> struct TCommonComparisonCategory<6> { using Type = partial_ordering; }; - -NAMESPACE_PRIVATE_END +template struct TCommonComparisonCategoryBasic { }; +template<> struct TCommonComparisonCategoryBasic<0> { using Type = strong_ordering; }; +template<> struct TCommonComparisonCategoryBasic<2> { using Type = partial_ordering; }; +template<> struct TCommonComparisonCategoryBasic<4> { using Type = weak_ordering; }; +template<> struct TCommonComparisonCategoryBasic<6> { using Type = partial_ordering; }; template -struct TCommonComparisonCategory - : NAMESPACE_PRIVATE::TCommonComparisonCategory<(0u | ... | +struct TCommonComparisonCategoryImpl + : TCommonComparisonCategoryBasic <(0u | ... | ( CSameAs ? 0u : CSameAs ? 4u : @@ -37,8 +35,13 @@ struct TCommonComparisonCategory )> { }; +NAMESPACE_PRIVATE_END + +template +using TCommonComparisonCategory = typename NAMESPACE_PRIVATE::TCommonComparisonCategoryImpl::Type; + template -concept CThreeWayComparesAs = CSameAs::Type, OrderingType>; +concept CThreeWayComparesAs = CSameAs, OrderingType>; template concept CThreeWayComparable = CWeaklyEqualityComparable && CPartiallyOrdered @@ -54,10 +57,7 @@ concept CThreeWayComparable = CWeaklyEqualityComparable && CPartiallyOrder }; template requires CThreeWayComparable -struct TCompareThreeWayResult -{ - using Type = decltype(DeclVal&>() <=> DeclVal&>()); -}; +using TCompareThreeWayResult = decltype(DeclVal&>() <=> DeclVal&>()); template concept CSynthThreeWayComparable = CThreeWayComparable || CTotallyOrdered; @@ -75,11 +75,8 @@ constexpr decltype(auto) SynthThreeWayCompare(T&& LHS, U&& RHS) } } -template -struct TSynthThreeWayResult -{ - using Type = decltype(SynthThreeWayCompare(DeclVal&>(), DeclVal&>())); -}; +template requires CSynthThreeWayComparable +using TSynthThreeWayResult = decltype(SynthThreeWayCompare(DeclVal&>(), DeclVal&>())); NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) diff --git a/Redcraft.Utility/Source/Public/Templates/Any.h b/Redcraft.Utility/Source/Public/Templates/Any.h index 2c94462..fc1bd32 100644 --- a/Redcraft.Utility/Source/Public/Templates/Any.h +++ b/Redcraft.Utility/Source/Public/Templates/Any.h @@ -437,7 +437,8 @@ template struct TIsTAny concept CTAny = NAMESPACE_PRIVATE::TIsTAny::Value; +template +concept CTAny = NAMESPACE_PRIVATE::TIsTAny::Value; using FAny = TAny; diff --git a/Redcraft.Utility/Source/Public/Templates/IntegerSequence.h b/Redcraft.Utility/Source/Public/Templates/IntegerSequence.h index 84a2706..3a6bf9a 100644 --- a/Redcraft.Utility/Source/Public/Templates/IntegerSequence.h +++ b/Redcraft.Utility/Source/Public/Templates/IntegerSequence.h @@ -18,7 +18,7 @@ NAMESPACE_PRIVATE_BEGIN #ifdef _MSC_VER template -struct TMakeIntegerSequence +struct TMakeIntegerSequenceImpl { using Type = typename __make_integer_seq; }; @@ -26,7 +26,7 @@ struct TMakeIntegerSequence #elif __has_builtin(__make_integer_seq) template -struct TMakeIntegerSequence +struct TMakeIntegerSequenceImpl { using Type = typename __make_integer_seq; }; @@ -34,13 +34,13 @@ struct TMakeIntegerSequence #else template -struct TMakeIntegerSequence +struct TMakeIntegerSequenceImpl { - using Type = typename TMakeIntegerSequence::Type; + using Type = typename TMakeIntegerSequenceImpl::Type; }; template -struct TMakeIntegerSequence<0, T, Ints...> +struct TMakeIntegerSequenceImpl<0, T, Ints...> { using Type = TIntegerSequence; }; @@ -53,7 +53,7 @@ template using TIndexSequence = TIntegerSequence; template -using TMakeIntegerSequence = typename NAMESPACE_PRIVATE::TMakeIntegerSequence::Type; +using TMakeIntegerSequence = typename NAMESPACE_PRIVATE::TMakeIntegerSequenceImpl::Type; template using TMakeIndexSequence = TMakeIntegerSequence; diff --git a/Redcraft.Utility/Source/Public/Templates/Optional.h b/Redcraft.Utility/Source/Public/Templates/Optional.h index 77681cb..54ebd3d 100644 --- a/Redcraft.Utility/Source/Public/Templates/Optional.h +++ b/Redcraft.Utility/Source/Public/Templates/Optional.h @@ -124,7 +124,8 @@ public: return *this; } - template requires CConstructibleFrom && CAssignableFrom && TAllowUnwrapping::Value + template requires CConstructibleFrom + && CAssignableFrom && TAllowUnwrapping::Value constexpr TOptional& operator=(const TOptional& InValue) { if (!InValue.IsValid()) @@ -143,7 +144,8 @@ public: return *this; } - template requires CConstructibleFrom && CAssignableFrom && TAllowUnwrapping::Value + template requires CConstructibleFrom + && CAssignableFrom && TAllowUnwrapping::Value constexpr TOptional& operator=(TOptional&& InValue) { if (!InValue.IsValid()) diff --git a/Redcraft.Utility/Source/Public/Templates/ReferenceWrapper.h b/Redcraft.Utility/Source/Public/Templates/ReferenceWrapper.h index 5a4fa70..719f97e 100644 --- a/Redcraft.Utility/Source/Public/Templates/ReferenceWrapper.h +++ b/Redcraft.Utility/Source/Public/Templates/ReferenceWrapper.h @@ -40,7 +40,7 @@ public: constexpr ReferencedType& Get() const { return *Pointer; } template - constexpr TInvokeResult::Type operator()(Types&&... Args) const + constexpr TInvokeResult operator()(Types&&... Args) const { return Invoke(Get(), Forward(Args)...); } @@ -101,17 +101,24 @@ constexpr TReferenceWrapper Ref(TReferenceWrapper InValue) NAMESPACE_PRIVATE_BEGIN -template struct TIsTReferenceWrapper : FFalse { }; -template struct TIsTReferenceWrapper> : FTrue { }; +template struct TIsTReferenceWrapperImpl : FFalse { }; +template struct TIsTReferenceWrapperImpl> : FTrue { }; + +template struct TUnwrapReferenceImpl { using Type = T; }; +template struct TUnwrapReferenceImpl> { using Type = T&; }; + +template struct TUnwrapRefDecayImpl { using Type = typename TUnwrapReferenceImpl>::Type; }; NAMESPACE_PRIVATE_END -template concept CTReferenceWrapper = NAMESPACE_PRIVATE::TIsTReferenceWrapper::Value; +template +concept CTReferenceWrapper = NAMESPACE_PRIVATE::TIsTReferenceWrapperImpl::Value; -template struct TUnwrapReference { using Type = T; }; -template struct TUnwrapReference> { using Type = T&; }; +template +using TUnwrapReference = typename NAMESPACE_PRIVATE::TUnwrapReferenceImpl::Type; -template struct TUnwrapRefDecay { using Type = typename TUnwrapReference>::Type; }; +template +using TUnwrapRefDecay = typename NAMESPACE_PRIVATE::TUnwrapRefDecayImpl::Type; template struct TOptional> @@ -168,7 +175,8 @@ public: TOptional& operator=(const TOptional& InValue) = default; TOptional& operator=(TOptional&& InValue) = default; - template requires CConstructibleFrom && CAssignableFrom && TAllowUnwrapping::Value + template requires CConstructibleFrom + && CAssignableFrom && TAllowUnwrapping::Value constexpr TOptional& operator=(const TOptional& InValue) { Reference = InValue.Reference; diff --git a/Redcraft.Utility/Source/Public/Templates/Tuple.h b/Redcraft.Utility/Source/Public/Templates/Tuple.h index c40b6fe..976fe3c 100644 --- a/Redcraft.Utility/Source/Public/Templates/Tuple.h +++ b/Redcraft.Utility/Source/Public/Templates/Tuple.h @@ -21,42 +21,107 @@ struct 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 TTupleElementIndex; +template +struct TTupleArityImpl; + +template +struct TTupleArityImpl> : TConstant { }; + +template +struct TTupleArityImpl> : TConstant { }; + +template +struct TTupleArityImpl> : TConstant { }; + +template +struct TTupleArityImpl> : TConstant { }; + +template +struct TTupleIndexImpl; template -struct TTupleElementIndex - : TConstant ? 0 : (TTupleElementIndex::Value == INDEX_NONE - ? INDEX_NONE : TTupleElementIndex::Value + 1)> -{ }; - -template -struct TTupleElementIndex : TConstant { }; - -template -struct TTupleElementType; - -template -struct TTupleElementType +struct TTupleIndexImpl> : TConstant>::Value + 1> { - static_assert(I < sizeof...(Types) + 1, "Tuple type index is invalid"); - using Type = TTupleElementType::Type; + static_assert(sizeof...(Types) != 0, "Non-existent types in tuple"); }; template -struct TTupleElementType<0, T, Types...> { using Type = T; }; +struct TTupleIndexImpl> : TConstant +{ + static_assert((true && ... && !CSameAs), "Duplicate type in tuple"); +}; + +template +struct TTupleIndexImpl> : TConstant { }; + +template +struct TTupleIndexImpl> : TTupleIndexImpl> { }; + +template +struct TTupleIndexImpl> : TTupleIndexImpl> { }; + +template +struct TTupleIndexImpl> : TTupleIndexImpl> { }; + +template +struct TTupleElementImpl; + +template +struct TTupleElementImpl> +{ + static_assert(I < sizeof...(Types) + 1, "Invalid index in tuple"); + using Type = TTupleElementImpl>::Type; +}; + +template +struct TTupleElementImpl<0, TTuple> { using Type = T; }; + +template +struct TTupleElementImpl> { }; template <> -struct TTupleElementType<0> { }; +struct TTupleElementImpl<0, TTuple<>> { }; + +template +struct TTupleElementImpl> { using Type = TAddConst>::Type>; }; + +template +struct TTupleElementImpl> { using Type = TAddVolatile>::Type>; }; + +template +struct TTupleElementImpl> { using Type = TAddCV>::Type>; }; + +template +struct TTupleConvertCopy : FTrue { }; + +template +struct TTupleConvertCopy + : TBoolConstant&, T> + || CConstructibleFrom&> + || CSameAs)> +{ }; + +template +struct TTupleConvertMove : FTrue { }; + +template +struct TTupleConvertMove + : TBoolConstant&&, T> + || CConstructibleFrom&&> + || CSameAs)> +{ }; template -struct TTupleElement +struct TTupleBasicElement { private: @@ -66,15 +131,15 @@ private: public: template - constexpr TTupleElement(Type&& Arg) + constexpr TTupleBasicElement(Type&& Arg) : Value(Forward(Arg)) { } - TTupleElement() = default; - TTupleElement(TTupleElement&&) = default; - TTupleElement(const TTupleElement&) = default; - TTupleElement& operator=(TTupleElement&&) = default; - TTupleElement& operator=(const TTupleElement&) = default; + TTupleBasicElement() = default; + TTupleBasicElement(TTupleBasicElement&&) = default; + TTupleBasicElement(const TTupleBasicElement&) = default; + TTupleBasicElement& operator=(TTupleBasicElement&&) = default; + TTupleBasicElement& operator=(const TTupleBasicElement&) = default; constexpr T& GetValue() & { return static_cast< T& >(Value); } constexpr const T& GetValue() const & { return static_cast(Value); } @@ -88,23 +153,23 @@ public: #if RS_TUPLE_ELEMENT_STATIC_ALIAS -#define DEFINE_TTupleElement(Index, Name) \ +#define DEFINE_TTupleBasicElement(Index, Name) \ template \ - struct TTupleElement \ + struct TTupleBasicElement \ { \ using Name##Type = T; \ Name##Type Name; \ \ template \ - constexpr TTupleElement(Type&& Arg) \ + constexpr TTupleBasicElement(Type&& Arg) \ : Name(Forward(Arg)) \ { } \ \ - TTupleElement() = default; \ - TTupleElement(TTupleElement&&) = default; \ - TTupleElement(const TTupleElement&) = default; \ - TTupleElement& operator=(TTupleElement&&) = default; \ - TTupleElement& operator=(const TTupleElement&) = default; \ + TTupleBasicElement() = default; \ + TTupleBasicElement(TTupleBasicElement&&) = default; \ + TTupleBasicElement(const TTupleBasicElement&) = default; \ + TTupleBasicElement& operator=(TTupleBasicElement&&) = default; \ + TTupleBasicElement& operator=(const TTupleBasicElement&) = default; \ \ constexpr T& GetValue() & { return static_cast< T& >(Name); } \ constexpr const T& GetValue() const & { return static_cast(Name); } \ @@ -116,38 +181,38 @@ public: constexpr const volatile T&& GetValue() const volatile&& { return static_cast(Name); } \ } -DEFINE_TTupleElement(0x0, First); -DEFINE_TTupleElement(0x1, Second); -DEFINE_TTupleElement(0x2, Third); -DEFINE_TTupleElement(0x3, Fourth); -DEFINE_TTupleElement(0x4, Fifth); -DEFINE_TTupleElement(0x5, Sixth); -DEFINE_TTupleElement(0x6, Seventh); -DEFINE_TTupleElement(0x7, Eighth); -DEFINE_TTupleElement(0x8, Ninth); -DEFINE_TTupleElement(0x9, Tenth); -DEFINE_TTupleElement(0xA, Eleventh); -DEFINE_TTupleElement(0xB, Twelfth); -DEFINE_TTupleElement(0xC, Thirteenth); -DEFINE_TTupleElement(0xD, Fourteenth); -DEFINE_TTupleElement(0xE, Fifteenth); -DEFINE_TTupleElement(0xF, Sixteenth); +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_TTupleElement +#undef DEFINE_TTupleBasicElement #endif template -constexpr TTuple::Type...> MakeTupleImpl(Types&&... Args) +constexpr TTuple...> MakeTupleImpl(Types&&... Args) { - return TTuple::Type...>(Forward(Args)...); + return TTuple...>(Forward(Args)...); } template struct TTupleImpl; template -struct TTupleImpl, Types...> : TTupleElement... +struct TTupleImpl, Types...> : TTupleBasicElement... { protected: @@ -155,12 +220,12 @@ protected: template explicit TTupleImpl(FForwardingConstructor, ArgTypes&&... Args) - : TTupleElement(Forward(Args))... + : TTupleBasicElement(Forward(Args))... { } template explicit TTupleImpl(FOtherTupleConstructor, TupleType&& InValue) - : TTupleElement(Forward(InValue).template GetValue())... + : TTupleBasicElement(Forward(InValue).template GetValue())... { } TTupleImpl(const TTupleImpl&) = default; @@ -180,7 +245,10 @@ struct TTupleHelper> template static constexpr void Assign(LHSTupleType& LHS, RHSTupleType&& RHS) { - static_assert(sizeof...(Indices) == LHS.ElementSize && LHS.ElementSize == RHS.ElementSize, "Cannot assign tuple from different size"); + static_assert(sizeof...(Indices) == TTupleArityImpl>::Value + && TTupleArityImpl>::Value == TTupleArityImpl>::Value, + "Cannot assign tuple from different size"); + ((LHS.template GetValue() = Forward(RHS).template GetValue()), ...); } @@ -218,6 +286,18 @@ struct TTupleHelper> 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 = typename NAMESPACE_PRIVATE::TTupleElementImpl::Type; + template struct TTuple : NAMESPACE_PRIVATE::TTupleImpl, Types...> { @@ -228,71 +308,32 @@ private: public: - static constexpr size_t ElementSize = sizeof...(Types); - - template struct TElementType : NAMESPACE_PRIVATE::TTupleElementType { }; - template struct TElementIndex : NAMESPACE_PRIVATE::TTupleElementIndex { }; - TTuple() = default; - - template requires (ElementSize > 0) && (sizeof...(ArgTypes) == ElementSize) + + template requires (sizeof...(Types) >= 1) && (sizeof...(ArgTypes) == sizeof...(Types)) && (true && ... && CConstructibleFrom) - && (true && ... && CConvertibleTo) - constexpr TTuple(ArgTypes&&... Args) - : Super(NAMESPACE_PRIVATE::ForwardingConstructor, Forward(Args)...) - { } - - template requires (ElementSize > 0) && (sizeof...(ArgTypes) == ElementSize) - && (true && ... && CConstructibleFrom) - && (!(true && ... && CConvertibleTo)) - constexpr explicit TTuple(ArgTypes&&... Args) + constexpr explicit (!(true && ... && CConvertibleTo)) TTuple(ArgTypes&&... Args) : Super(NAMESPACE_PRIVATE::ForwardingConstructor, Forward(Args)...) { } - template requires (sizeof...(OtherTypes) == ElementSize) + template requires (sizeof...(OtherTypes) == sizeof...(Types)) && (true && ... && CConstructibleFrom) - && ((ElementSize != 1) || !(CConvertibleTo&, typename TElementType<0>::Type> - || CConstructibleFrom::Type, const TTuple&> - || CSameAs::Type, typename TTuple::template TElementType<0>::Type>)) - && (true && ... && CConvertibleTo) - constexpr TTuple(const TTuple& InValue) + && NAMESPACE_PRIVATE::TTupleConvertCopy::Value + constexpr explicit (!(true && ... && CConvertibleTo)) TTuple(const TTuple& InValue) : Super(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue) { } - template requires (sizeof...(OtherTypes) == ElementSize) - && (true && ... && CConstructibleFrom) - && ((ElementSize != 1) || !(CConvertibleTo&, typename TElementType<0>::Type> - || CConstructibleFrom::Type, const TTuple&> - || CSameAs::Type, typename TTuple::template TElementType<0>::Type>)) - && (!(true && ... && CConvertibleTo)) - constexpr explicit TTuple(const TTuple& InValue) - : Super(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue) - { } - - template requires (sizeof...(OtherTypes) == ElementSize) + template requires (sizeof...(OtherTypes) == sizeof...(Types)) && (true && ... && CConstructibleFrom) - && ((ElementSize != 1) || !(CConvertibleTo&&, typename TElementType<0>::Type> - || CConstructibleFrom::Type, TTuple&&> - || CSameAs::Type, typename TTuple::template TElementType<0>::Type>)) - && (true && ... && CConvertibleTo) - constexpr TTuple(TTuple&& InValue) - : Super(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue)) - { } - - template requires (sizeof...(OtherTypes) == ElementSize) - && (true && ... && CConstructibleFrom) - && ((ElementSize != 1) || !(CConvertibleTo&&, typename TElementType<0>::Type> - || CConstructibleFrom::Type, TTuple&&> - || CSameAs::Type, typename TTuple::template TElementType<0>::Type>)) - && (!(true && ... && CConvertibleTo)) - constexpr explicit TTuple(TTuple&& InValue) + && NAMESPACE_PRIVATE::TTupleConvertMove::Value + constexpr explicit (!(true && ... && CConvertibleTo)) TTuple(TTuple&& InValue) : Super(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue)) { } TTuple(const TTuple&) = default; TTuple(TTuple&&) = default; - template requires (sizeof...(OtherTypes) == ElementSize) + template requires (sizeof...(OtherTypes) == sizeof...(Types)) && (true && ... && CAssignableFrom) constexpr TTuple& operator=(const TTuple& InValue) { @@ -300,7 +341,7 @@ public: return *this; } - template requires (sizeof...(OtherTypes) == ElementSize) + template requires (sizeof...(OtherTypes) == sizeof...(Types)) && (true && ... && CAssignableFrom) constexpr TTuple& operator=(TTuple&& InValue) { @@ -311,59 +352,59 @@ public: TTuple& operator=(const TTuple&) = default; TTuple& operator=(TTuple&&) = default; - template requires (I < ElementSize) constexpr TElementType::Type& GetValue() & { return static_cast< NAMESPACE_PRIVATE::TTupleElement::Type, I>& >(*this).GetValue(); } - template requires (I < ElementSize) constexpr const TElementType::Type& GetValue() const & { return static_cast::Type, I>& >(*this).GetValue(); } - template requires (I < ElementSize) constexpr volatile TElementType::Type& GetValue() volatile& { return static_cast< volatile NAMESPACE_PRIVATE::TTupleElement::Type, I>& >(*this).GetValue(); } - template requires (I < ElementSize) constexpr const volatile TElementType::Type& GetValue() const volatile& { return static_cast::Type, I>& >(*this).GetValue(); } - template requires (I < ElementSize) constexpr TElementType::Type&& GetValue() && { return static_cast< NAMESPACE_PRIVATE::TTupleElement::Type, I>&&>(*this).GetValue(); } - template requires (I < ElementSize) constexpr const TElementType::Type&& GetValue() const && { return static_cast::Type, I>&&>(*this).GetValue(); } - template requires (I < ElementSize) constexpr volatile TElementType::Type&& GetValue() volatile&& { return static_cast< volatile NAMESPACE_PRIVATE::TTupleElement::Type, I>&&>(*this).GetValue(); } - template requires (I < ElementSize) constexpr const volatile TElementType::Type&& GetValue() const volatile&& { return static_cast::Type, I>&&>(*this).GetValue(); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() & { return static_cast< NAMESPACE_PRIVATE::TTupleBasicElement>, I>& >(*this).GetValue(); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() const & { return static_cast>, I>& >(*this).GetValue(); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() volatile& { return static_cast< volatile NAMESPACE_PRIVATE::TTupleBasicElement>, I>& >(*this).GetValue(); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() const volatile& { return static_cast>, I>& >(*this).GetValue(); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() && { return static_cast< NAMESPACE_PRIVATE::TTupleBasicElement>, I>&&>(*this).GetValue(); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() const && { return static_cast>, I>&&>(*this).GetValue(); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() volatile&& { return static_cast< volatile NAMESPACE_PRIVATE::TTupleBasicElement>, I>&&>(*this).GetValue(); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() const volatile&& { return static_cast>, I>&&>(*this).GetValue(); } - template requires (TElementIndex::Value != INDEX_NONE) constexpr T& GetValue() & { return static_cast< TTuple& >(*this).GetValue::Value>(); } - template requires (TElementIndex::Value != INDEX_NONE) constexpr const T& GetValue() const & { return static_cast(*this).GetValue::Value>(); } - template requires (TElementIndex::Value != INDEX_NONE) constexpr volatile T& GetValue() volatile& { return static_cast< volatile TTuple& >(*this).GetValue::Value>(); } - template requires (TElementIndex::Value != INDEX_NONE) constexpr const volatile T& GetValue() const volatile& { return static_cast(*this).GetValue::Value>(); } - template requires (TElementIndex::Value != INDEX_NONE) constexpr T&& GetValue() && { return static_cast< TTuple&&>(*this).GetValue::Value>(); } - template requires (TElementIndex::Value != INDEX_NONE) constexpr const T&& GetValue() const && { return static_cast(*this).GetValue::Value>(); } - template requires (TElementIndex::Value != INDEX_NONE) constexpr volatile T&& GetValue() volatile&& { return static_cast< volatile TTuple&&>(*this).GetValue::Value>(); } - template requires (TElementIndex::Value != INDEX_NONE) constexpr const volatile T&& GetValue() const volatile&& { return static_cast(*this).GetValue::Value>(); } + template constexpr decltype(auto) GetValue() & { return static_cast< TTuple& >(*this).GetValue>>(); } + template constexpr decltype(auto) GetValue() const & { return static_cast(*this).GetValue>>(); } + template constexpr decltype(auto) GetValue() volatile& { return static_cast< volatile TTuple& >(*this).GetValue>>(); } + template constexpr decltype(auto) GetValue() const volatile& { return static_cast(*this).GetValue>>(); } + template constexpr decltype(auto) GetValue() && { return static_cast< TTuple&&>(*this).GetValue>>(); } + template constexpr decltype(auto) GetValue() const && { return static_cast(*this).GetValue>>(); } + template constexpr decltype(auto) GetValue() volatile&& { return static_cast< volatile TTuple&&>(*this).GetValue>>(); } + template constexpr decltype(auto) GetValue() const volatile&& { return static_cast(*this).GetValue>>(); } - template requires CInvocable constexpr auto Apply(F&& Func) & { return Helper::Apply(Forward(Func), static_cast< TTuple& >(*this)); } - template requires CInvocable constexpr auto Apply(F&& Func) const & { return Helper::Apply(Forward(Func), static_cast(*this)); } - template requires CInvocable constexpr auto Apply(F&& Func) volatile& { return Helper::Apply(Forward(Func), static_cast< volatile TTuple& >(*this)); } - template requires CInvocable constexpr auto Apply(F&& Func) const volatile& { return Helper::Apply(Forward(Func), static_cast(*this)); } - template requires CInvocable constexpr auto Apply(F&& Func) && { return Helper::Apply(Forward(Func), static_cast< TTuple&&>(*this)); } - template requires CInvocable constexpr auto Apply(F&& Func) const && { return Helper::Apply(Forward(Func), static_cast(*this)); } - template requires CInvocable constexpr auto Apply(F&& Func) volatile&& { return Helper::Apply(Forward(Func), static_cast< volatile TTuple&&>(*this)); } - template requires CInvocable constexpr auto Apply(F&& Func) const volatile&& { return Helper::Apply(Forward(Func), static_cast(*this)); } + template requires CInvocable constexpr decltype(auto) Apply(F&& Func) & { return Helper::Apply(Forward(Func), static_cast< TTuple& >(*this)); } + template requires CInvocable constexpr decltype(auto) Apply(F&& Func) const & { return Helper::Apply(Forward(Func), static_cast(*this)); } + template requires CInvocable constexpr decltype(auto) Apply(F&& Func) volatile& { return Helper::Apply(Forward(Func), static_cast< volatile TTuple& >(*this)); } + template requires CInvocable constexpr decltype(auto) Apply(F&& Func) const volatile& { return Helper::Apply(Forward(Func), static_cast(*this)); } + template requires CInvocable constexpr decltype(auto) Apply(F&& Func) && { return Helper::Apply(Forward(Func), static_cast< TTuple&&>(*this)); } + template requires CInvocable constexpr decltype(auto) Apply(F&& Func) const && { return Helper::Apply(Forward(Func), static_cast(*this)); } + template requires CInvocable constexpr decltype(auto) Apply(F&& Func) volatile&& { return Helper::Apply(Forward(Func), static_cast< volatile TTuple&&>(*this)); } + template requires CInvocable constexpr decltype(auto) Apply(F&& Func) const volatile&& { return Helper::Apply(Forward(Func), static_cast(*this)); } - template requires CInvocable constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) & { return Helper::ApplyAfter(Forward(Func), static_cast< TTuple& >(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const & { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) volatile& { return Helper::ApplyAfter(Forward(Func), static_cast< volatile TTuple& >(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const volatile& { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) && { return Helper::ApplyAfter(Forward(Func), static_cast< TTuple&&>(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const && { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) volatile&& { return Helper::ApplyAfter(Forward(Func), static_cast< volatile TTuple&&>(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const volatile&& { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyAfter(F&& Func, ArgTypes&&... Args) & { return Helper::ApplyAfter(Forward(Func), static_cast< TTuple& >(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyAfter(F&& Func, ArgTypes&&... Args) const & { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyAfter(F&& Func, ArgTypes&&... Args) volatile& { return Helper::ApplyAfter(Forward(Func), static_cast< volatile TTuple& >(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyAfter(F&& Func, ArgTypes&&... Args) const volatile& { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyAfter(F&& Func, ArgTypes&&... Args) && { return Helper::ApplyAfter(Forward(Func), static_cast< TTuple&&>(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyAfter(F&& Func, ArgTypes&&... Args) const && { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyAfter(F&& Func, ArgTypes&&... Args) volatile&& { return Helper::ApplyAfter(Forward(Func), static_cast< volatile TTuple&&>(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyAfter(F&& Func, ArgTypes&&... Args) const volatile&& { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) & { return Helper::ApplyBefore(Forward(Func), static_cast< TTuple& >(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const & { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) volatile& { return Helper::ApplyBefore(Forward(Func), static_cast< volatile TTuple& >(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const volatile& { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) && { return Helper::ApplyBefore(Forward(Func), static_cast< TTuple&&>(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const && { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) volatile&& { return Helper::ApplyBefore(Forward(Func), static_cast< volatile TTuple&&>(*this), Forward(Args)...); } - template requires CInvocable constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const volatile&& { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyBefore(F&& Func, ArgTypes&&... Args) & { return Helper::ApplyBefore(Forward(Func), static_cast< TTuple& >(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyBefore(F&& Func, ArgTypes&&... Args) const & { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyBefore(F&& Func, ArgTypes&&... Args) volatile& { return Helper::ApplyBefore(Forward(Func), static_cast< volatile TTuple& >(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyBefore(F&& Func, ArgTypes&&... Args) const volatile& { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyBefore(F&& Func, ArgTypes&&... Args) && { return Helper::ApplyBefore(Forward(Func), static_cast< TTuple&&>(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyBefore(F&& Func, ArgTypes&&... Args) const && { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyBefore(F&& Func, ArgTypes&&... Args) volatile&& { return Helper::ApplyBefore(Forward(Func), static_cast< volatile TTuple&&>(*this), Forward(Args)...); } + template requires CInvocable constexpr decltype(auto) ApplyBefore(F&& Func, ArgTypes&&... Args) const volatile&& { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires (true && ... && (CInvocable && !CSameAs>)) constexpr auto Transform(F&& Func) & { return Helper::Transform(Forward(Func), static_cast< TTuple& >(*this)); } - template requires (true && ... && (CInvocable && !CSameAs>)) constexpr auto Transform(F&& Func) const & { return Helper::Transform(Forward(Func), static_cast(*this)); } - template requires (true && ... && (CInvocable && !CSameAs>)) constexpr auto Transform(F&& Func) volatile& { return Helper::Transform(Forward(Func), static_cast< volatile TTuple& >(*this)); } - template requires (true && ... && (CInvocable && !CSameAs>)) constexpr auto Transform(F&& Func) const volatile& { return Helper::Transform(Forward(Func), static_cast(*this)); } - template requires (true && ... && (CInvocable && !CSameAs>)) constexpr auto Transform(F&& Func) && { return Helper::Transform(Forward(Func), static_cast< TTuple&&>(*this)); } - template requires (true && ... && (CInvocable && !CSameAs>)) constexpr auto Transform(F&& Func) const && { return Helper::Transform(Forward(Func), static_cast(*this)); } - template requires (true && ... && (CInvocable && !CSameAs>)) constexpr auto Transform(F&& Func) volatile&& { return Helper::Transform(Forward(Func), static_cast< volatile TTuple&&>(*this)); } - template requires (true && ... && (CInvocable && !CSameAs>)) constexpr auto Transform(F&& Func) const volatile&& { return Helper::Transform(Forward(Func), static_cast(*this)); } + template requires (true && ... && (CInvocable && !CSameAs>)) constexpr decltype(auto) Transform(F&& Func) & { return Helper::Transform(Forward(Func), static_cast< TTuple& >(*this)); } + template requires (true && ... && (CInvocable && !CSameAs>)) constexpr decltype(auto) Transform(F&& Func) const & { return Helper::Transform(Forward(Func), static_cast(*this)); } + template requires (true && ... && (CInvocable && !CSameAs>)) constexpr decltype(auto) Transform(F&& Func) volatile& { return Helper::Transform(Forward(Func), static_cast< volatile TTuple& >(*this)); } + template requires (true && ... && (CInvocable && !CSameAs>)) constexpr decltype(auto) Transform(F&& Func) const volatile& { return Helper::Transform(Forward(Func), static_cast(*this)); } + template requires (true && ... && (CInvocable && !CSameAs>)) constexpr decltype(auto) Transform(F&& Func) && { return Helper::Transform(Forward(Func), static_cast< TTuple&&>(*this)); } + template requires (true && ... && (CInvocable && !CSameAs>)) constexpr decltype(auto) Transform(F&& Func) const && { return Helper::Transform(Forward(Func), static_cast(*this)); } + template requires (true && ... && (CInvocable && !CSameAs>)) constexpr decltype(auto) Transform(F&& Func) volatile&& { return Helper::Transform(Forward(Func), static_cast< volatile TTuple&&>(*this)); } + template requires (true && ... && (CInvocable && !CSameAs>)) constexpr decltype(auto) Transform(F&& Func) const volatile&& { return Helper::Transform(Forward(Func), static_cast(*this)); } template requires CConstructibleFrom constexpr T Construct() & { return Helper::template Construct(static_cast< TTuple& >(*this)); } template requires CConstructibleFrom constexpr T Construct() const & { return Helper::template Construct(static_cast(*this)); } @@ -376,12 +417,20 @@ public: constexpr size_t GetTypeHash() const requires (true && ... && CHashable) { - return [this](TIndexSequence) -> size_t { return HashCombine(NAMESPACE_REDCRAFT::GetTypeHash(GetValue())...); } (TMakeIndexSequence()); + return [this](TIndexSequence) -> size_t + { + return HashCombine(NAMESPACE_REDCRAFT::GetTypeHash(GetValue())...); + } + (TMakeIndexSequence()); } constexpr void Swap(TTuple& InValue) requires (true && ... && (CMoveConstructible&& CSwappable)) { - [&A = *this, &B = InValue](TIndexSequence) { ((NAMESPACE_REDCRAFT::Swap(A.template GetValue(), B.template GetValue())), ...); } (TMakeIndexSequence()); + [&A = *this, &B = InValue](TIndexSequence) + { + ((NAMESPACE_REDCRAFT::Swap(A.template GetValue(), B.template GetValue())), ...); + } + (TMakeIndexSequence()); } }; @@ -392,28 +441,10 @@ TTuple(Types...) -> TTuple; template using TPair = TTuple; -NAMESPACE_PRIVATE_BEGIN - -template struct TIsTTuple : FFalse { }; -template struct TIsTTuple> : FTrue { }; - -NAMESPACE_PRIVATE_END - -template concept CTTuple = NAMESPACE_PRIVATE::TIsTTuple::Value; - -template requires CTTuple> -struct TTupleElementSize : TConstant::ElementSize> { }; - -template requires CTTuple> -struct TTupleElementType { using Type = TCopyCVRef, typename TRemoveCVRef::template TElementType::Type>; }; - -template requires CTTuple> -struct TTupleElementIndex : TupleType::template TElementIndex { }; - template -constexpr TTuple::Type...> MakeTuple(Types&&... Args) +constexpr TTuple...> MakeTuple(Types&&... Args) { - return TTuple::Type...>(Forward(Args)...); + return TTuple...>(Forward(Args)...); } template @@ -476,7 +507,7 @@ template struct TTupleCatForward, TIndexSequence> { template - static constexpr auto F(ForwardType&& ForwardTuple, TTupleType&& InValue) + static constexpr decltype(auto) F(ForwardType&& ForwardTuple, TTupleType&& InValue) { return ForwardAsTuple(Forward(ForwardTuple).template GetValue()..., Forward(InValue).template GetValue()...); } @@ -486,15 +517,18 @@ template struct TTupleCatImpl { template - static constexpr auto F(ForwardType&& ForwardTuple, TTupleType&& InValue, OtherTTupleTypes&&... OtherValue) + static constexpr decltype(auto) F(ForwardType&& ForwardTuple, TTupleType&& InValue, OtherTTupleTypes&&... OtherValue) { - return F(TTupleCatForward::Value>, TMakeIndexSequence::Value>>::F(Forward(ForwardTuple), Forward(InValue)), Forward(OtherValue)...); + return F(TTupleCatForward< + TMakeIndexSequence>>, + TMakeIndexSequence>>> + ::F(Forward(ForwardTuple), Forward(InValue)), Forward(OtherValue)...); } template - static constexpr auto F(ForwardType&& ForwardTuple) + static constexpr decltype(auto) F(ForwardType&& ForwardTuple) { - return TTupleCatMake::Value>>::F(Forward(ForwardTuple)); + return TTupleCatMake>>::F(Forward(ForwardTuple)); } }; @@ -546,13 +580,13 @@ struct TTupleVisitImpl> NAMESPACE_PRIVATE_END -template requires (true && ... && (CTTuple>)) -struct TTupleCatResult { using Type = typename NAMESPACE_PRIVATE::TTupleCatResultImpl..., NAMESPACE_PRIVATE::FTupleEndFlag>::Type; }; +template requires (true && ... && CTTuple>) +using TTupleCatResult = typename NAMESPACE_PRIVATE::TTupleCatResultImpl..., NAMESPACE_PRIVATE::FTupleEndFlag>::Type;; -template requires (true && ... && (CTTuple>)) -constexpr auto TupleCat(TTupleTypes&&... Args) +template requires (true && ... && CTTuple>) +constexpr decltype(auto) TupleCat(TTupleTypes&&... Args) { - using R = typename TTupleCatResult::Type; + using R = TTupleCatResult; if constexpr (sizeof...(Args) == 0) return R(); else return NAMESPACE_PRIVATE::TTupleCatImpl::F(Forward(Args)...); } @@ -565,9 +599,9 @@ constexpr bool operator==(const TTuple& LHS, const TTuple requires ((sizeof...(LHSTypes) == sizeof...(RHSTypes)) && (true && ... && (CSynthThreeWayComparable))) -constexpr typename TCommonComparisonCategory::Type...>::Type operator<=>(const TTuple& LHS, const TTuple& RHS) +constexpr TCommonComparisonCategory...> operator<=>(const TTuple& LHS, const TTuple& RHS) { - using R = typename TCommonComparisonCategory::Type...>::Type; + using R = TCommonComparisonCategory...>; return NAMESPACE_PRIVATE::TTupleThreeWay>::F(LHS, RHS); } @@ -577,7 +611,8 @@ constexpr void VisitTuple(F&& Func) { } template constexpr void VisitTuple(F&& Func, FirstTupleType&& FirstTuple, TupleTypes&&... Tuples) { - NAMESPACE_PRIVATE::TTupleVisitImpl::Value>>::F(Forward(Func), Forward(FirstTuple), Forward(Tuples)...); + NAMESPACE_PRIVATE::TTupleVisitImpl>>> + ::F(Forward(Func), Forward(FirstTuple), Forward(Tuples)...); } template requires requires { typename TTuple...>; } @@ -600,8 +635,8 @@ NAMESPACE_REDCRAFT_END NAMESPACE_STD_BEGIN // Support structure binding, should not be directly used -template struct tuple_size> : integral_constant>::Value> { }; -template struct tuple_element> { using type = typename NAMESPACE_REDCRAFT::TTupleElementType>::Type; }; +template struct tuple_size> : integral_constant>> { }; +template struct tuple_element> { using type = NAMESPACE_REDCRAFT::TTupleElement>; }; NAMESPACE_STD_END @@ -610,14 +645,14 @@ NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) // Support structure binding, should not be directly used -template constexpr typename TTupleElementType>::Type& get( NAMESPACE_REDCRAFT::TTuple& InValue) { return static_cast< typename TTupleElementType>::Type& >(InValue.template GetValue()); } -template constexpr const typename TTupleElementType>::Type& get(const NAMESPACE_REDCRAFT::TTuple& InValue) { return static_cast>::Type& >(InValue.template GetValue()); } -template constexpr volatile typename TTupleElementType>::Type& get( volatile NAMESPACE_REDCRAFT::TTuple& InValue) { return static_cast< volatile typename TTupleElementType>::Type& >(InValue.template GetValue()); } -template constexpr const volatile typename TTupleElementType>::Type& get(const volatile NAMESPACE_REDCRAFT::TTuple& InValue) { return static_cast>::Type& >(InValue.template GetValue()); } -template constexpr typename TTupleElementType>::Type&& get( NAMESPACE_REDCRAFT::TTuple&& InValue) { return static_cast< typename TTupleElementType>::Type&&>(InValue.template GetValue()); } -template constexpr const typename TTupleElementType>::Type&& get(const NAMESPACE_REDCRAFT::TTuple&& InValue) { return static_cast>::Type&&>(InValue.template GetValue()); } -template constexpr volatile typename TTupleElementType>::Type&& get( volatile NAMESPACE_REDCRAFT::TTuple&& InValue) { return static_cast< volatile typename TTupleElementType>::Type&&>(InValue.template GetValue()); } -template constexpr const volatile typename TTupleElementType>::Type&& get(const volatile NAMESPACE_REDCRAFT::TTuple&& InValue) { return static_cast>::Type&&>(InValue.template GetValue()); } +template constexpr decltype(auto) get( TTuple& InValue) { return static_cast< TTuple& >(InValue).template GetValue(); } +template constexpr decltype(auto) get(const TTuple& InValue) { return static_cast& >(InValue).template GetValue(); } +template constexpr decltype(auto) get( volatile TTuple& InValue) { return static_cast< volatile TTuple& >(InValue).template GetValue(); } +template constexpr decltype(auto) get(const volatile TTuple& InValue) { return static_cast& >(InValue).template GetValue(); } +template constexpr decltype(auto) get( TTuple&& InValue) { return static_cast< TTuple&&>(InValue).template GetValue(); } +template constexpr decltype(auto) get(const TTuple&& InValue) { return static_cast&&>(InValue).template GetValue(); } +template constexpr decltype(auto) get( volatile TTuple&& InValue) { return static_cast< volatile TTuple&&>(InValue).template GetValue(); } +template constexpr decltype(auto) get(const volatile TTuple&& InValue) { return static_cast&&>(InValue).template GetValue(); } NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) diff --git a/Redcraft.Utility/Source/Public/Templates/Variant.h b/Redcraft.Utility/Source/Public/Templates/Variant.h index 61e57fc..b175e93 100644 --- a/Redcraft.Utility/Source/Public/Templates/Variant.h +++ b/Redcraft.Utility/Source/Public/Templates/Variant.h @@ -13,35 +13,83 @@ NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) +template requires (true && ... && CDestructible) +struct TVariant; + NAMESPACE_PRIVATE_BEGIN -template -struct TVariantAlternativeIndex; +template struct TIsTVariant : FFalse { }; +template struct TIsTVariant> : FTrue { }; + +template +struct TVariantNumImpl; + +template +struct TVariantNumImpl> : TConstant { }; + +template +struct TVariantNumImpl> : TConstant { }; + +template +struct TVariantNumImpl> : TConstant { }; + +template +struct TVariantNumImpl> : TConstant { }; + +template +struct TVariantIndexImpl; template -struct TVariantAlternativeIndex - : TConstant ? 0 : (TVariantAlternativeIndex::Value == INDEX_NONE - ? INDEX_NONE : TVariantAlternativeIndex::Value + 1)> -{ }; - -template -struct TVariantAlternativeIndex : TConstant { }; - -template -struct TVariantAlternativeType; - -template -struct TVariantAlternativeType +struct TVariantIndexImpl> : TConstant>::Value + 1> { - static_assert(I < sizeof...(Types) + 1, "Variant type index is invalid"); - using Type = TVariantAlternativeType::Type; + static_assert(sizeof...(Types) != 0, "Non-existent types in variant"); }; template -struct TVariantAlternativeType<0, T, Types...> { using Type = T; }; +struct TVariantIndexImpl> : TConstant +{ + static_assert((true && ... && !CSameAs), "Duplicate type in variant"); +}; + +template +struct TVariantIndexImpl> : TConstant { }; + +template +struct TVariantIndexImpl> : TVariantIndexImpl> { }; + +template +struct TVariantIndexImpl> : TVariantIndexImpl> { }; + +template +struct TVariantIndexImpl> : TVariantIndexImpl> { }; + +template +struct TVariantAlternativeImpl; + +template +struct TVariantAlternativeImpl> +{ + static_assert(I < sizeof...(Types) + 1, "Invalid index in variant"); + using Type = TVariantAlternativeImpl>::Type; +}; + +template +struct TVariantAlternativeImpl<0, TVariant> { using Type = T; }; + +template +struct TVariantAlternativeImpl> { }; template <> -struct TVariantAlternativeType<0> { }; +struct TVariantAlternativeImpl<0, TVariant<>> { }; + +template +struct TVariantAlternativeImpl> { using Type = TAddConst>::Type>; }; + +template +struct TVariantAlternativeImpl> { using Type = TAddVolatile>::Type>; }; + +template +struct TVariantAlternativeImpl> { using Type = TAddCV>::Type>; }; template struct TVariantSelectedType; @@ -78,14 +126,21 @@ struct TVariantSelectedType NAMESPACE_PRIVATE_END -template requires (true && ... && CDestructible) && (sizeof...(Types) < 0xFF) +template +concept CTVariant = NAMESPACE_PRIVATE::TIsTVariant::Value; + +template +inline constexpr size_t TVariantNum = NAMESPACE_PRIVATE::TVariantNumImpl::Value; + +template +inline constexpr size_t TVariantIndex = NAMESPACE_PRIVATE::TVariantIndexImpl::Value; + +template +using TVariantAlternative = typename NAMESPACE_PRIVATE::TVariantAlternativeImpl::Type; + +template requires (true && ... && CDestructible) struct TVariant { - static constexpr size_t AlternativeSize = sizeof...(Types); - - template struct TAlternativeType : NAMESPACE_PRIVATE::TVariantAlternativeType { }; - template struct TAlternativeIndex : NAMESPACE_PRIVATE::TVariantAlternativeIndex { }; - constexpr TVariant() : TypeIndex(0xFF) { }; constexpr TVariant(FInvalid) : TVariant() { }; @@ -102,19 +157,18 @@ struct TVariant if (IsValid()) MoveConstructImpl[InValue.GetIndex()](&Value, &InValue.Value); } - template requires (I < AlternativeSize) - && CConstructibleFrom::Type, ArgTypes...> + template requires (I < sizeof...(Types)) + && CConstructibleFrom>, ArgTypes...> constexpr explicit TVariant(TInPlaceIndex, ArgTypes&&... Args) : TypeIndex(I) { - using SelectedType = typename TAlternativeType::Type; + using SelectedType = TVariantAlternative>; new(&Value) SelectedType(Forward(Args)...); } - template requires (TAlternativeIndex::Value != INDEX_NONE) - && CConstructibleFrom::Value>::Type, ArgTypes...> + template requires CConstructibleFrom constexpr explicit TVariant(TInPlaceType, ArgTypes&&... Args) - : TVariant(InPlaceIndex::Value>, Forward(Args)...) + : TVariant(InPlaceIndex>>, Forward(Args)...) { } template requires NAMESPACE_PRIVATE::TVariantSelectedType, Types...>::Value @@ -175,35 +229,34 @@ struct TVariant { using SelectedType = typename NAMESPACE_PRIVATE::TVariantSelectedType, Types...>::Type; - if (GetIndex() == TAlternativeIndex::Value) GetValue() = Forward(InValue); + if (GetIndex() == TVariantIndex>) GetValue() = Forward(InValue); else { Reset(); new(&Value) SelectedType(Forward(InValue)); - TypeIndex = TAlternativeIndex::Value; + TypeIndex = TVariantIndex>; } return *this; } - template requires (I < AlternativeSize) - && CConstructibleFrom::Type, ArgTypes...> - constexpr typename TAlternativeType::Type& Emplace(ArgTypes&&... Args) + template requires (I < sizeof...(Types)) + && CConstructibleFrom>, ArgTypes...> + constexpr TVariantAlternative>& Emplace(ArgTypes&&... Args) { Reset(); - using SelectedType = typename TAlternativeType::Type; + using SelectedType = TVariantAlternative>; SelectedType* Result = new(&Value) SelectedType(Forward(Args)...); TypeIndex = I; return *Result; } - template requires (TAlternativeIndex::Value != INDEX_NONE) - && CConstructibleFrom::Value>::Type, ArgTypes...> + template requires CConstructibleFrom constexpr T& Emplace(ArgTypes&&... Args) { - return Emplace::Value>(Forward(Args)...); + return Emplace>>(Forward(Args)...); } constexpr const type_info& GetTypeInfo() const { return IsValid() ? *TypeInfos[GetIndex()] : typeid(void); } @@ -212,24 +265,24 @@ struct TVariant constexpr bool IsValid() const { return TypeIndex != 0xFF; } constexpr explicit operator bool() const { return TypeIndex != 0xFF; } - template constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == I : false; } - template constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == TAlternativeIndex::Value : false; } + template constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == I : false; } + template constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == TVariantIndex> : false; } - template requires (I < AlternativeSize) constexpr typename TAlternativeType::Type& GetValue() & { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast< TAlternativeType::Type*>(&Value); } - template requires (I < AlternativeSize) constexpr typename TAlternativeType::Type&& GetValue() && { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast< TAlternativeType::Type*>(&Value)); } - template requires (I < AlternativeSize) constexpr const typename TAlternativeType::Type& GetValue() const& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast::Type*>(&Value); } - template requires (I < AlternativeSize) constexpr const typename TAlternativeType::Type&& GetValue() const&& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast::Type*>(&Value)); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() & { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast< TVariantAlternative>*>(&Value); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() && { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast< TVariantAlternative>*>(&Value)); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() const& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast>*>(&Value); } + template requires (I < sizeof...(Types)) constexpr decltype(auto) GetValue() const&& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast>*>(&Value)); } - template requires (TAlternativeIndex::Value != INDEX_NONE) constexpr T& GetValue() & { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast< T*>(&Value); } - template requires (TAlternativeIndex::Value != INDEX_NONE) constexpr T&& GetValue() && { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast< T*>(&Value)); } - template requires (TAlternativeIndex::Value != INDEX_NONE) constexpr const T& GetValue() const& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast(&Value); } - template requires (TAlternativeIndex::Value != INDEX_NONE) constexpr const T&& GetValue() const&& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast(&Value)); } + template constexpr decltype(auto) GetValue() & { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast< T*>(&Value); } + template constexpr decltype(auto) GetValue() && { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast< T*>(&Value)); } + template constexpr decltype(auto) GetValue() const& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast(&Value); } + template constexpr decltype(auto) GetValue() const&& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast(&Value)); } - template requires (I < AlternativeSize) constexpr typename TAlternativeType::Type& Get( typename TAlternativeType::Type& DefaultValue) & { return HoldsAlternative() ? GetValue() : DefaultValue; } - template requires (I < AlternativeSize) constexpr const typename TAlternativeType::Type& Get(const typename TAlternativeType::Type& DefaultValue) const& { return HoldsAlternative() ? GetValue() : DefaultValue; } + template requires (I < sizeof...(Types)) constexpr decltype(auto) Get( TVariantAlternative>& DefaultValue) & { return HoldsAlternative() ? GetValue() : DefaultValue; } + template requires (I < sizeof...(Types)) constexpr decltype(auto) Get(const TVariantAlternative>& DefaultValue) const& { return HoldsAlternative() ? GetValue() : DefaultValue; } - template requires (TAlternativeIndex::Value != INDEX_NONE) constexpr T& Get(T& DefaultValue)& { return HoldsAlternative() ? GetValue() : DefaultValue; } - template requires (TAlternativeIndex::Value != INDEX_NONE) constexpr const T& Get(const T& DefaultValue) const& { return HoldsAlternative() ? GetValue() : DefaultValue; } + template constexpr decltype(auto) Get( T& DefaultValue) & { return HoldsAlternative() ? GetValue() : DefaultValue; } + template constexpr decltype(auto) Get(const T& DefaultValue) const& { return HoldsAlternative() ? GetValue() : DefaultValue; } template requires (true && ... && CInvocable) FORCEINLINE decltype(auto) Visit(F&& Func) & @@ -409,24 +462,6 @@ constexpr bool operator==(const TVariant& LHS, FInvalid) return !LHS.IsValid(); } -NAMESPACE_PRIVATE_BEGIN - -template struct TIsTVariant : FFalse { }; -template struct TIsTVariant> : FTrue { }; - -NAMESPACE_PRIVATE_END - -template concept CTVariant = NAMESPACE_PRIVATE::TIsTVariant::Value; - -template requires CTVariant> -struct TVariantAlternativeSize : TConstant { }; - -template requires CTVariant> -struct TVariantAlternativeType { using Type = TCopyCV, typename TRemoveCVRef::template TAlternativeType::Type>; }; - -template requires CTVariant> -struct TVariantAlternativeIndex : VariantType::template TAlternativeIndex { }; - NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/TypeTraits/Miscellaneous.h b/Redcraft.Utility/Source/Public/TypeTraits/Miscellaneous.h index 9668166..9bc3f4a 100644 --- a/Redcraft.Utility/Source/Public/TypeTraits/Miscellaneous.h +++ b/Redcraft.Utility/Source/Public/TypeTraits/Miscellaneous.h @@ -25,8 +25,8 @@ struct TMaximum : TMaximum<(First < Second ? Second : NAMESPACE_PRIVATE_END -template inline constexpr size_t ArrayRank = NAMESPACE_STD::rank_v; -template inline constexpr size_t ArrayExtent = NAMESPACE_STD::extent_v; +template inline constexpr size_t TRank = NAMESPACE_STD::rank_v; +template inline constexpr size_t TExtent = NAMESPACE_STD::extent_v; template concept CSameAs = NAMESPACE_STD::is_same_v; template concept CBaseOf = NAMESPACE_STD::is_base_of_v;