From 0c6bf06a56a7eba64d6281e1e2bf25e6bcc3ea77 Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Wed, 23 Mar 2022 17:49:30 +0800 Subject: [PATCH] refactor(templates): optimize visit functions for TOptional, TVariant and TAny, add necessary constraints --- .../Source/Public/Templates/Any.h | 22 ++++-- .../Source/Public/Templates/Optional.h | 30 ++++---- .../Source/Public/Templates/Variant.h | 68 +++++++++---------- 3 files changed, 64 insertions(+), 56 deletions(-) diff --git a/Redcraft.Utility/Source/Public/Templates/Any.h b/Redcraft.Utility/Source/Public/Templates/Any.h index 83e0033..4ccd141 100644 --- a/Redcraft.Utility/Source/Public/Templates/Any.h +++ b/Redcraft.Utility/Source/Public/Templates/Any.h @@ -335,13 +335,23 @@ struct TAny constexpr void* GetData() { return IsInline() ? &InlineValue : DynamicValue; } constexpr const void* GetData() const { return IsInline() ? &InlineValue : DynamicValue; } - template constexpr T& GetValue() & { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast< T*>(GetData()); } - template constexpr T&& GetValue() && { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast< T*>(GetData())); } - template constexpr const T& GetValue() const& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast(GetData()); } - template constexpr const T&& GetValue() const&& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast(GetData())); } + template requires TIsSame::Type>::Value && TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value + constexpr T& GetValue() & { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast< T*>(GetData()); } - template constexpr T Get(T&& DefaultValue) && { return HoldsAlternative() ? GetValue() : DefaultValue; } - template constexpr T Get(T&& DefaultValue) const& { return HoldsAlternative() ? GetValue() : DefaultValue; } + template requires TIsSame::Type>::Value && TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value + constexpr T&& GetValue() && { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast< T*>(GetData())); } + + template requires TIsSame::Type>::Value && TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value + constexpr const T& GetValue() const& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast(GetData()); } + + template requires TIsSame::Type>::Value && TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value + constexpr const T&& GetValue() const&& { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast(GetData())); } + + template requires TIsSame::Type>::Value&& TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value + constexpr T& Get( T& DefaultValue) & { return HoldsAlternative() ? GetValue() : DefaultValue; } + + template requires TIsSame::Type>::Value&& TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value + constexpr const T& Get(const T& DefaultValue) const& { return HoldsAlternative() ? GetValue() : DefaultValue; } void Reset() { diff --git a/Redcraft.Utility/Source/Public/Templates/Optional.h b/Redcraft.Utility/Source/Public/Templates/Optional.h index c9154bb..550694a 100644 --- a/Redcraft.Utility/Source/Public/Templates/Optional.h +++ b/Redcraft.Utility/Source/Public/Templates/Optional.h @@ -9,12 +9,12 @@ NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) -template requires (TIsObject::Value && !TIsArray::Value&& TIsDestructible::Value) +template requires TIsObject::Value && (!TIsArray::Value) && TIsDestructible::Value struct TOptional { public: - using Type = OptionalType; + using ValueType = OptionalType; constexpr TOptional() : bIsValid(false) { } @@ -29,7 +29,7 @@ public: template requires TIsConstructible::Value && (!TIsSame::Type, FInPlace>::Value) && (!TIsSame::Type, TOptional>::Value) - constexpr explicit(!TIsConvertible::Value) TOptional(T&& InValue) + constexpr explicit (!TIsConvertible::Value) TOptional(T&& InValue) : TOptional(InPlace, Forward(InValue)) { } @@ -46,14 +46,14 @@ public: } template requires TIsConstructible::Value - constexpr explicit(!TIsConvertible::Value) TOptional(const TOptional& InValue) + constexpr explicit (!TIsConvertible::Value) TOptional(const TOptional& InValue) : bIsValid(InValue.IsValid()) { if (InValue.IsValid()) new(&Value) OptionalType(InValue.GetValue()); } template requires TIsConstructible::Value - constexpr explicit(!TIsConvertible::Value) TOptional(TOptional&& InValue) + constexpr explicit (!TIsConvertible::Value) TOptional(TOptional&& InValue) : bIsValid(InValue.IsValid()) { if (InValue.IsValid()) new(&Value) OptionalType(MoveTemp(InValue.GetValue())); @@ -61,7 +61,7 @@ public: constexpr ~TOptional() { - Reset(); + if constexpr (!TIsTriviallyDestructible::Value) Reset(); } constexpr TOptional& operator=(const TOptional& InValue) @@ -168,11 +168,14 @@ public: constexpr bool IsValid() const { return bIsValid; } constexpr explicit operator bool() const { return bIsValid; } + + constexpr void* GetData() { return &Value; } + constexpr const void* GetData() const { return &Value; } - constexpr OptionalType& GetValue() & { checkf(IsValid(), TEXT("It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead.")); return *(OptionalType*)&Value; } - constexpr OptionalType&& GetValue() && { checkf(IsValid(), TEXT("It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead.")); return MoveTemp(*(OptionalType*)&Value); } - constexpr const OptionalType& GetValue() const& { checkf(IsValid(), TEXT("It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead.")); return *(OptionalType*)&Value; } - constexpr const OptionalType&& GetValue() const&& { checkf(IsValid(), TEXT("It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead.")); return MoveTemp(*(OptionalType*)&Value); } + constexpr OptionalType& GetValue() & { checkf(IsValid(), TEXT("It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead.")); return *reinterpret_cast< OptionalType*>(&Value); } + constexpr OptionalType&& GetValue() && { checkf(IsValid(), TEXT("It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast< OptionalType*>(&Value)); } + constexpr const OptionalType& GetValue() const& { checkf(IsValid(), TEXT("It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead.")); return *reinterpret_cast(&Value); } + constexpr const OptionalType&& GetValue() const&& { checkf(IsValid(), TEXT("It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast(&Value)); } constexpr const OptionalType* operator->() const { return &GetValue(); } constexpr OptionalType* operator->() { return &GetValue(); } @@ -182,11 +185,8 @@ public: constexpr const OptionalType& operator*() const& { return GetValue(); } constexpr const OptionalType&& operator*() const&& { return GetValue(); } - template - constexpr OptionalType Get(T&& DefaultValue) && { return IsValid() ? GetValue() : DefaultValue; } - - template - constexpr OptionalType Get(T&& DefaultValue) const& { return IsValid() ? GetValue() : DefaultValue; } + constexpr OptionalType& Get( OptionalType& DefaultValue) & { return IsValid() ? GetValue() : DefaultValue; } + constexpr const OptionalType& Get(const OptionalType& DefaultValue) const& { return IsValid() ? GetValue() : DefaultValue; } constexpr void Reset() { diff --git a/Redcraft.Utility/Source/Public/Templates/Variant.h b/Redcraft.Utility/Source/Public/Templates/Variant.h index 53baa2f..92cd43c 100644 --- a/Redcraft.Utility/Source/Public/Templates/Variant.h +++ b/Redcraft.Utility/Source/Public/Templates/Variant.h @@ -72,8 +72,7 @@ struct TVariantSelectedType template constexpr void VariantDestroy(void* InValue) { - if constexpr (!TIsDestructible::Value) check_no_entry(); - else if constexpr (!TIsTriviallyDestructible::Value) + if constexpr (!TIsTriviallyDestructible::Value) { typedef T DestructOptionalType; reinterpret_cast(InValue)->DestructOptionalType::~DestructOptionalType(); @@ -153,8 +152,7 @@ struct TVariantHelper template constexpr R VariantVisitLValue(F&& Func, void* Arg) { - if constexpr (!TIsInvocableResult::Value) check_no_entry(); - else if constexpr(TIsVoid::Value) Invoke(Forward(Func), *reinterpret_cast(Arg)); + if constexpr(TIsVoid::Value) Invoke(Forward(Func), *reinterpret_cast(Arg)); else return InvokeResult(Forward(Func), *reinterpret_cast(Arg)); } @@ -164,8 +162,7 @@ using FVariantVisitLValueFunc = R(*)(F&&, void*); template constexpr R VariantVisitRValue(F&& Func, void* Arg) { - if constexpr (!TIsInvocableResult::Value) check_no_entry(); - else if constexpr (TIsVoid::Value) Invoke(Forward(Func), MoveTemp(*reinterpret_cast(Arg))); + if constexpr (TIsVoid::Value) Invoke(Forward(Func), MoveTemp(*reinterpret_cast(Arg))); else return InvokeResult(Forward(Func), MoveTemp(*reinterpret_cast(Arg))); } @@ -175,8 +172,7 @@ using FVariantVisitRValueFunc = R(*)(F&&, void*); template constexpr R VariantVisitConstLValue(F&& Func, const void* Arg) { - if constexpr (!TIsInvocableResult::Value) check_no_entry(); - else if constexpr (TIsVoid::Value) Invoke(Forward(Func), *reinterpret_cast(Arg)); + if constexpr (TIsVoid::Value) Invoke(Forward(Func), *reinterpret_cast(Arg)); else return InvokeResult(Forward(Func), *reinterpret_cast(Arg)); } @@ -186,8 +182,7 @@ using FVariantVisitConstLValueFunc = R(*)(F&&, const void*); template constexpr R VariantVisitConstRValue(F&& Func, const void* Arg) { - if constexpr (!TIsInvocableResult::Value) check_no_entry(); - else if constexpr (TIsVoid::Value) Invoke(Forward(Func), MoveTemp(*reinterpret_cast(Arg))); + if constexpr (TIsVoid::Value) Invoke(Forward(Func), MoveTemp(*reinterpret_cast(Arg))); else return InvokeResult(Forward(Func), MoveTemp(*reinterpret_cast(Arg))); } @@ -208,7 +203,7 @@ NAMESPACE_PRIVATE_END template requires (true && ... && (TIsObject::Value && !TIsArray::Value && TIsDestructible::Value)) struct TVariant { - struct FAlternativeSize : TConstant { }; + static constexpr size_t AlternativeSize = sizeof...(Types); template struct TAlternativeType : NAMESPACE_PRIVATE::TVariantAlternativeType { }; template struct TAlternativeIndex : NAMESPACE_PRIVATE::TVariantAlternativeIndex { }; @@ -229,7 +224,7 @@ struct TVariant if (GetIndex() != INDEX_NONE) FHelper::MoveConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); } - template requires (I < FAlternativeSize::Value) + template requires (I < AlternativeSize) && TIsConstructible::Type, ArgTypes...>::Value constexpr explicit TVariant(TInPlaceIndex, ArgTypes&&... Args) : TypeIndex(I) @@ -252,7 +247,7 @@ struct TVariant constexpr ~TVariant() { - Reset(); + if constexpr (!(true && ... && TIsTriviallyDestructible::Value)) Reset(); } constexpr TVariant& operator=(const TVariant& InValue) @@ -313,7 +308,7 @@ struct TVariant return *this; } - template requires (I < FAlternativeSize::Value) + template requires (I < AlternativeSize) && TIsConstructible::Type, ArgTypes...>::Value constexpr typename TAlternativeType::Type& Emplace(ArgTypes&&... Args) { @@ -343,23 +338,23 @@ struct TVariant constexpr void* GetData() { return &Value; } constexpr const void* GetData() const { return &Value; } - template 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 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 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 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 < 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 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 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 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 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 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 typename TAlternativeType::Type Get(typename TAlternativeType::Type&& DefaultValue) && { return HoldsAlternative() ? GetValue() : DefaultValue; } - template constexpr typename TAlternativeType::Type Get(typename TAlternativeType::Type&& DefaultValue) const& { return HoldsAlternative() ? GetValue() : DefaultValue; } + 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 constexpr T Get(T&& DefaultValue) && { return HoldsAlternative() ? GetValue() : DefaultValue; } - template constexpr T Get(T&& 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 + template requires (true && ... && TIsInvocable::Value) constexpr auto Visit(F&& Func) & { using ReturnType = typename TCommonType::Type...>::Type; @@ -367,7 +362,7 @@ struct TVariant return ReturnType(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitLValueFuncs[GetIndex()](Forward(Func), &Value)); } - template + template requires (true && ... && TIsInvocable::Value) constexpr auto Visit(F&& Func) && { using ReturnType = typename TCommonType::Type...>::Type; @@ -375,7 +370,7 @@ struct TVariant return ReturnType(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitRValueFuncs[GetIndex()](Forward(Func), &Value)); } - template + template requires (true && ... && TIsInvocable::Value) constexpr auto Visit(F&& Func) const& { using ReturnType = typename TCommonType::Type...>::Type; @@ -383,7 +378,7 @@ struct TVariant return ReturnType(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitConstLValueFuncs[GetIndex()](Forward(Func), &Value)); } - template + template requires (true && ... && TIsInvocable::Value) constexpr auto Visit(F&& Func) const&& { using ReturnType = typename TCommonType::Type...>::Type; @@ -391,28 +386,28 @@ struct TVariant return ReturnType(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitConstRValueFuncs[GetIndex()](Forward(Func), &Value)); } - template + template requires (true && ... && TIsInvocableResult::Value) constexpr R Visit(F&& Func) & { checkf(IsValid(), "It is an error to call Visit() on an wrong TVariant. Please either check IsValid()."); return R(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitLValueFuncs[GetIndex()](Forward(Func), &Value)); } - template + template requires (true && ... && TIsInvocableResult::Value) constexpr R Visit(F&& Func) && { checkf(IsValid(), "It is an error to call Visit() on an wrong TVariant. Please either check IsValid()."); return R(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitRValueFuncs[GetIndex()](Forward(Func), &Value)); } - template + template requires (true && ... && TIsInvocableResult::Value) constexpr R Visit(F&& Func) const& { checkf(IsValid(), "It is an error to call Visit() on an wrong TVariant. Please either check IsValid()."); return R(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitConstLValueFuncs[GetIndex()](Forward(Func), &Value)); } - template + template requires (true && ... && TIsInvocableResult::Value) constexpr R Visit(F&& Func) const&& { checkf(IsValid(), "It is an error to call Visit() on an wrong TVariant. Please either check IsValid()."); @@ -423,7 +418,10 @@ struct TVariant { if (GetIndex() == INDEX_NONE) return; - FHelper::DestroyFuncs[GetIndex()](&Value); + if constexpr (!(true && ... && TIsTriviallyDestructible::Value)) + { + FHelper::DestroyFuncs[GetIndex()](&Value); + } TypeIndex = INDEX_NONE; }