From 01eec5d4c0bdf229ba13caf52ea3f6295b2f68e7 Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Sat, 3 Dec 2022 23:11:05 +0800 Subject: [PATCH] feat(templates): add TTypeSequence and meta tools --- .../Source/Public/Templates/Function.h | 4 +- .../Source/Public/Templates/IntegerSequence.h | 66 ----- .../Source/Public/Templates/Meta.h | 280 ++++++++++++++++++ .../Source/Public/Templates/Templates.h | 2 +- .../Source/Public/Templates/Tuple.h | 73 +---- .../Source/Public/Templates/Utility.h | 17 ++ .../Source/Public/Templates/Variant.h | 82 +---- .../Source/Public/TypeTraits/Common.h | 2 +- 8 files changed, 325 insertions(+), 201 deletions(-) delete mode 100644 Redcraft.Utility/Source/Public/Templates/IntegerSequence.h create mode 100644 Redcraft.Utility/Source/Public/Templates/Meta.h diff --git a/Redcraft.Utility/Source/Public/Templates/Function.h b/Redcraft.Utility/Source/Public/Templates/Function.h index b7bc1e8..8949180 100644 --- a/Redcraft.Utility/Source/Public/Templates/Function.h +++ b/Redcraft.Utility/Source/Public/Templates/Function.h @@ -2,7 +2,7 @@ #include "CoreTypes.h" #include "Templates/Any.h" -#include "Templates/Tuple.h" +#include "Templates/Meta.h" #include "Templates/Invoke.h" #include "Memory/Alignment.h" #include "Templates/Utility.h" @@ -88,7 +88,7 @@ class TFunctionImpl public: using ResultType = Ret; - using ArgumentType = TTuple; + using ArgumentType = TTypeSequence; TFunctionImpl() = default; TFunctionImpl(const TFunctionImpl&) = default; diff --git a/Redcraft.Utility/Source/Public/Templates/IntegerSequence.h b/Redcraft.Utility/Source/Public/Templates/IntegerSequence.h deleted file mode 100644 index 3a6bf9a..0000000 --- a/Redcraft.Utility/Source/Public/Templates/IntegerSequence.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include "CoreTypes.h" - -NAMESPACE_REDCRAFT_BEGIN -NAMESPACE_MODULE_BEGIN(Redcraft) -NAMESPACE_MODULE_BEGIN(Utility) - -template -struct TIntegerSequence -{ - using ValueType = T; - static constexpr size_t Size() { return sizeof...(Ints); } -}; - -NAMESPACE_PRIVATE_BEGIN - -#ifdef _MSC_VER - -template -struct TMakeIntegerSequenceImpl -{ - using Type = typename __make_integer_seq; -}; - -#elif __has_builtin(__make_integer_seq) - -template -struct TMakeIntegerSequenceImpl -{ - using Type = typename __make_integer_seq; -}; - -#else - -template -struct TMakeIntegerSequenceImpl -{ - using Type = typename TMakeIntegerSequenceImpl::Type; -}; - -template -struct TMakeIntegerSequenceImpl<0, T, Ints...> -{ - using Type = TIntegerSequence; -}; - -#endif - -NAMESPACE_PRIVATE_END - -template -using TIndexSequence = TIntegerSequence; - -template -using TMakeIntegerSequence = typename NAMESPACE_PRIVATE::TMakeIntegerSequenceImpl::Type; - -template -using TMakeIndexSequence = TMakeIntegerSequence; - -template -using TIndexSequenceFor = TMakeIndexSequence; - -NAMESPACE_MODULE_END(Utility) -NAMESPACE_MODULE_END(Redcraft) -NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Templates/Meta.h b/Redcraft.Utility/Source/Public/Templates/Meta.h new file mode 100644 index 0000000..4f7d879 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Templates/Meta.h @@ -0,0 +1,280 @@ +#pragma once + +#include "CoreTypes.h" +#include "Templates/Utility.h" +#include "Templates/Container.h" +#include "TypeTraits/TypeTraits.h" + +NAMESPACE_REDCRAFT_BEGIN +NAMESPACE_MODULE_BEGIN(Redcraft) +NAMESPACE_MODULE_BEGIN(Utility) + +template +struct TIntegerSequence +{ + using ValueType = T; + static constexpr size_t Num() { return sizeof...(Ints); } + static constexpr const T* GetData() { return NAMESPACE_REDCRAFT::GetData({ Ints... }); } +}; + +NAMESPACE_PRIVATE_BEGIN + +#ifdef _MSC_VER + +template +struct TMakeIntegerSequenceImpl +{ + using Type = typename __make_integer_seq; +}; + +#elif __has_builtin(__make_integer_seq) + +template +struct TMakeIntegerSequenceImpl +{ + using Type = typename __make_integer_seq; +}; + +#else + +template +struct TMakeIntegerSequenceImpl +{ + using Type = typename TMakeIntegerSequenceImpl::Type; +}; + +template +struct TMakeIntegerSequenceImpl<0, T, Ints...> +{ + using Type = TIntegerSequence; +}; + +#endif + +NAMESPACE_PRIVATE_END + +template +using TIndexSequence = TIntegerSequence; + +template +using TMakeIntegerSequence = typename NAMESPACE_PRIVATE::TMakeIntegerSequenceImpl::Type; + +template +using TMakeIndexSequence = TMakeIntegerSequence; + +template +using TIndexSequenceFor = TMakeIndexSequence; + +template +struct TTypeSequence { }; + +NAMESPACE_PRIVATE_BEGIN + +template struct TIsTIntegerSequence : FFalse { }; +template struct TIsTIntegerSequence> : FTrue { }; + +template struct TIsTIndexSequence : FFalse { }; +template struct TIsTIndexSequence> : FTrue { }; + +template struct TIsTTypeSequence : FFalse { }; +template struct TIsTTypeSequence> : FTrue { }; + +NAMESPACE_PRIVATE_END + +// Unlike other places such as CTTuple, cv-qualifiers are not ignored here +// This is done to simplify the logic and make it easier to use it + +template +concept CTIntegerSequence = NAMESPACE_PRIVATE::TIsTIntegerSequence::Value; + +template +concept CTIndexSequence = NAMESPACE_PRIVATE::TIsTIndexSequence::Value; + +template +concept CTTypeSequence = NAMESPACE_PRIVATE::TIsTTypeSequence::Value; + +NAMESPACE_BEGIN(Meta) + +NAMESPACE_PRIVATE_BEGIN + +template +struct TFrontImpl; + +template +struct TFrontImpl> +{ + using Type = T; +}; + +template +struct TPopImpl; + +template +struct TPopImpl> +{ + using Type = TTypeSequence; +}; + +template +struct TPushImpl; + +template +struct TPushImpl> +{ + using Type = TTypeSequence; +}; + +NAMESPACE_PRIVATE_END + +template +using TFront = typename NAMESPACE_PRIVATE::TFrontImpl::Type; + +template +using TPop = typename NAMESPACE_PRIVATE::TPopImpl::Type; + +template +using TPush = typename NAMESPACE_PRIVATE::TPushImpl::Type; + +NAMESPACE_PRIVATE_BEGIN + +template +struct TTypeCountImpl +{ + static constexpr size_t Value = (CSameAs> ? 1 : 0) + TTypeCountImpl>::Value; +}; + +template +struct TTypeCountImpl> +{ + static constexpr size_t Value = 0; +}; + +NAMESPACE_PRIVATE_END + +template +inline constexpr size_t TTypeCount = NAMESPACE_PRIVATE::TTypeCountImpl::Value; + +template +concept CExistentType = CTTypeSequence && TTypeCount > 0; + +template +concept CDuplicateType = CTTypeSequence && TTypeCount > 1; + +NAMESPACE_PRIVATE_BEGIN + +template +struct TSizeImpl; + +template +struct TSizeImpl> +{ + static constexpr size_t Value = sizeof...(Ts); +}; + +template +struct TIndexImpl +{ + static constexpr size_t Value = CSameAs> ? I : TIndexImpl>::Value; +}; + +template +struct TIndexImpl> +{ + static constexpr size_t Value = INDEX_NONE; +}; + +template +struct TIndexAssert +{ + static_assert( Meta::CExistentType< T, TSequence>, "T is non-existent types in type sequence"); + static_assert(!Meta::CDuplicateType, "T is duplicate type in type sequence" ); + static constexpr size_t Value = TIndexImpl<0, T, TSequence>::Value; +}; + +template +struct TTypeImpl +{ + using Type = typename TTypeImpl>::Type; +}; + +template +struct TTypeImpl<0, TSequence> +{ + using Type = TFront; +}; + +template +struct TTypeImpl +{ + using Type = void; +}; + +template +struct TTypeAssert +{ + static_assert(I < TSizeImpl::Value, "I is invalid index in type sequence"); + static constexpr size_t SafeIndex = I < TSizeImpl::Value ? I : INDEX_NONE; + using Type = TCopyCV::Type>; +}; + +NAMESPACE_PRIVATE_END + +template +inline constexpr size_t TSize = NAMESPACE_PRIVATE::TSizeImpl::Value; + +template +inline constexpr size_t TIndex = NAMESPACE_PRIVATE::TIndexAssert::Value; + +template +using TType = typename NAMESPACE_PRIVATE::TTypeAssert::Type; + +NAMESPACE_PRIVATE_BEGIN + +template +struct TUniqueTypeSequenceImpl +{ + using FrontType = TFront; + using NextSequence = TPop; + using NextUniqueSequence = typename TUniqueTypeSequenceImpl::Type; + using Type = TConditional, TPush, NextUniqueSequence>; +}; + +template <> +struct TUniqueTypeSequenceImpl> +{ + using Type = TTypeSequence<>; +}; + +NAMESPACE_PRIVATE_END + +template +using TUniqueTypeSequence = typename NAMESPACE_PRIVATE::TUniqueTypeSequenceImpl::Type; + +NAMESPACE_PRIVATE_BEGIN + +template +struct TOverload +{ + using F = T(*)(T); + operator F() const { return nullptr; } +}; + +template +struct TOverloadSetImpl; + +template +struct TOverloadSetImpl> : public TOverload... { }; + +template +struct TOverloadSet : public TOverloadSetImpl> { }; + +NAMESPACE_PRIVATE_END + +template +using TOverloadResolution = decltype(DeclVal>()(DeclVal())); + +NAMESPACE_END(Meta) + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Templates/Templates.h b/Redcraft.Utility/Source/Public/Templates/Templates.h index b03fec6..db3a7d6 100644 --- a/Redcraft.Utility/Source/Public/Templates/Templates.h +++ b/Redcraft.Utility/Source/Public/Templates/Templates.h @@ -9,7 +9,7 @@ #include "Templates/Optional.h" #include "Templates/Variant.h" #include "Templates/Any.h" -#include "Templates/IntegerSequence.h" +#include "Templates/Meta.h" #include "Templates/Tuple.h" #include "Templates/TypeHash.h" #include "Templates/Function.h" diff --git a/Redcraft.Utility/Source/Public/Templates/Tuple.h b/Redcraft.Utility/Source/Public/Templates/Tuple.h index ddab60b..a2bd017 100644 --- a/Redcraft.Utility/Source/Public/Templates/Tuple.h +++ b/Redcraft.Utility/Source/Public/Templates/Tuple.h @@ -1,11 +1,11 @@ #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/IntegerSequence.h" #include "Templates/ReferenceWrapper.h" #include @@ -21,7 +21,7 @@ class TTuple; NAMESPACE_PRIVATE_BEGIN -template struct TIsTTuple : FFalse { }; +template struct TIsTTuple : FFalse { }; template struct TIsTTuple> : FTrue { }; struct FForwardingConstructor { explicit FForwardingConstructor() = default; }; @@ -34,72 +34,23 @@ template struct TTupleArityImpl; template -struct TTupleArityImpl> : TConstant { }; - -template -struct TTupleArityImpl> : TConstant { }; - -template -struct TTupleArityImpl> : TConstant { }; - -template -struct TTupleArityImpl> : TConstant { }; +struct TTupleArityImpl> : TConstant>> { }; template struct TTupleIndexImpl; -template -struct TTupleIndexImpl> : TConstant>::Value + 1> -{ - static_assert(sizeof...(Ts) != 0, "Non-existent types in tuple"); -}; - template -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> { }; +struct TTupleIndexImpl> : TConstant>> { }; template struct TTupleElementImpl; -template -struct TTupleElementImpl> +template +struct TTupleElementImpl> { - static_assert(I < sizeof...(Ts) + 1, "Invalid index in tuple"); - using Type = TTupleElementImpl>::Type; + using Type = Meta::TType>; }; -template -struct TTupleElementImpl<0, TTuple> { using Type = T; }; - -template -struct TTupleElementImpl> { }; - -template <> -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 { }; @@ -247,8 +198,8 @@ public: template static constexpr void Assign(LHSTupleType& LHS, RHSTupleType&& RHS) { - static_assert(sizeof...(Indices) == TTupleArityImpl>::Value - && TTupleArityImpl>::Value == TTupleArityImpl>::Value, + static_assert(sizeof...(Indices) == TTupleArityImpl>::Value + && TTupleArityImpl>::Value == TTupleArityImpl>::Value, "Cannot assign tuple from different size"); ((LHS.template GetValue() = Forward(RHS).template GetValue()), ...); @@ -292,13 +243,13 @@ template concept CTTuple = NAMESPACE_PRIVATE::TIsTTuple>::Value; template -inline constexpr size_t TTupleArity = NAMESPACE_PRIVATE::TTupleArityImpl::Value; +inline constexpr size_t TTupleArity = NAMESPACE_PRIVATE::TTupleArityImpl>::Value; template -inline constexpr size_t TTupleIndex = NAMESPACE_PRIVATE::TTupleIndexImpl::Value; +inline constexpr size_t TTupleIndex = NAMESPACE_PRIVATE::TTupleIndexImpl>::Value; template -using TTupleElement = typename NAMESPACE_PRIVATE::TTupleElementImpl::Type; +using TTupleElement = TCopyCV>::Type>; template class TTuple : public NAMESPACE_PRIVATE::TTupleImpl, Ts...> diff --git a/Redcraft.Utility/Source/Public/Templates/Utility.h b/Redcraft.Utility/Source/Public/Templates/Utility.h index 4f9571a..2cabd3e 100644 --- a/Redcraft.Utility/Source/Public/Templates/Utility.h +++ b/Redcraft.Utility/Source/Public/Templates/Utility.h @@ -117,6 +117,23 @@ inline constexpr FIgnore Ignore; \ } +// TOverloaded Usage Example +// +// Visit(TOverloaded { +// [](auto A) { ... }, +// [](double A) { ... }, +// [](const FString& A) { ... }, +// }, Target); +// +template +struct TOverloaded : Ts... +{ + using Ts::operator()...; +}; + +template +TOverloaded(Ts...) -> TOverloaded; + NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Templates/Variant.h b/Redcraft.Utility/Source/Public/Templates/Variant.h index fcb9f83..0ef5a95 100644 --- a/Redcraft.Utility/Source/Public/Templates/Variant.h +++ b/Redcraft.Utility/Source/Public/Templates/Variant.h @@ -5,6 +5,7 @@ #include "Templates/Utility.h" #include "Templates/TypeHash.h" #include "TypeTraits/TypeTraits.h" +#include "Templates/Meta.h" #include "Memory/MemoryOperator.h" #include "Miscellaneous/Compare.h" #include "Miscellaneous/AssertionMacros.h" @@ -21,86 +22,27 @@ NAMESPACE_PRIVATE_BEGIN template struct TIsTVariant : FFalse { }; template struct TIsTVariant> : FTrue { }; -// This class is to avoid conflicting with sizeof...(Ts) > 0 constraints when using TVariant<> in tool templates -template -struct TVariantProxy { }; - -template +template struct TVariantNumImpl; template -struct TVariantNumImpl> : TConstant { }; +struct TVariantNumImpl> : TConstant>> { }; -template -struct TVariantNumImpl> : TConstant { }; - -template -struct TVariantNumImpl> : TConstant { }; - -template -struct TVariantNumImpl> : TConstant { }; - -template +template struct TVariantIndexImpl; -template -struct TVariantIndexImpl> : TConstant>::Value + 1> -{ - static_assert(sizeof...(Ts) != 0, "Non-existent types in variant"); -}; - template -struct TVariantIndexImpl> : TConstant -{ - static_assert((true && ... && !CSameAs), "Duplicate type in variant"); -}; +struct TVariantIndexImpl> : TConstant>> { }; -template -struct TVariantIndexImpl> : TConstant { }; - -template -struct TVariantIndexImpl> : TVariantIndexImpl> { }; - -template -struct TVariantIndexImpl> : TVariantIndexImpl> { }; - -template -struct TVariantIndexImpl> : TVariantIndexImpl> { }; - -template -struct TVariantIndexImpl> : TVariantIndexImpl> { }; - -template +template struct TVariantAlternativeImpl; -template -struct TVariantAlternativeImpl> +template +struct TVariantAlternativeImpl> { - static_assert(I < sizeof...(Ts) + 1, "Invalid index in variant"); - using Type = TVariantAlternativeImpl>::Type; + using Type = Meta::TType>; }; -template -struct TVariantAlternativeImpl<0, TVariantProxy> { using Type = T; }; - -template -struct TVariantAlternativeImpl> { }; - -template <> -struct TVariantAlternativeImpl<0, TVariantProxy<>> { }; - -template -struct TVariantAlternativeImpl> : TVariantAlternativeImpl> { }; - -template -struct TVariantAlternativeImpl> { using Type = TAddConst>::Type>; }; - -template -struct TVariantAlternativeImpl> { using Type = TAddVolatile>::Type>; }; - -template -struct TVariantAlternativeImpl> { using Type = TAddCV>::Type>; }; - template struct TVariantSelectedType; @@ -140,13 +82,13 @@ template concept CTVariant = NAMESPACE_PRIVATE::TIsTVariant>::Value; template -inline constexpr size_t TVariantNum = NAMESPACE_PRIVATE::TVariantNumImpl::Value; +inline constexpr size_t TVariantNum = NAMESPACE_PRIVATE::TVariantNumImpl>::Value; template -inline constexpr size_t TVariantIndex = NAMESPACE_PRIVATE::TVariantIndexImpl::Value; +inline constexpr size_t TVariantIndex = NAMESPACE_PRIVATE::TVariantIndexImpl>::Value; template -using TVariantAlternative = typename NAMESPACE_PRIVATE::TVariantAlternativeImpl::Type; +using TVariantAlternative = TCopyCV>::Type>; template requires (sizeof...(Ts) > 0 && (true && ... && CDestructible)) class TVariant diff --git a/Redcraft.Utility/Source/Public/TypeTraits/Common.h b/Redcraft.Utility/Source/Public/TypeTraits/Common.h index 7ab2502..4cee50a 100644 --- a/Redcraft.Utility/Source/Public/TypeTraits/Common.h +++ b/Redcraft.Utility/Source/Public/TypeTraits/Common.h @@ -16,7 +16,7 @@ NAMESPACE_MODULE_BEGIN(Utility) template struct TBasicCommonType { }; // The class template is a customization point that allows users to influence the result of TCommonReference for user -template typename TQualifiers, template typename UQualifiers> struct TBasicCommonReference { }; +template typename TQualifiers, template typename UQualifiers> struct TBasicCommonReference { }; NAMESPACE_PRIVATE_BEGIN