refactor(templates): add constraints to reduce duplicate code on TAny etc
This commit is contained in:
parent
5f4b0d8c22
commit
943c7c5991
@ -10,7 +10,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
|
||||
#define CARRIES_DEPENDENCY [[carries_dependency]]
|
||||
#define DEPRECATED(Message) [[deprecated(Message)]]
|
||||
#define FALLTHROUGH [[fallthrough]]
|
||||
#define NODISCARD(Message) [[nodiscard(Message)]]
|
||||
#define NODISCARD [[nodiscard]]
|
||||
#define MAYBE_UNUSED [[maybe_unused]]
|
||||
#define LIKELY [[likely]]
|
||||
#define UNLIKELY [[unlikely]]
|
||||
|
@ -135,7 +135,7 @@ struct TAny
|
||||
|
||||
constexpr TAny() : TypeInfo(Typeid(void)), RTTI(nullptr) { }
|
||||
|
||||
TAny(FInvalid) : TAny() { }
|
||||
constexpr TAny(FInvalid) : TAny() { }
|
||||
|
||||
TAny(const TAny& InValue)
|
||||
: TypeInfo(InValue.TypeInfo), RTTI(InValue.RTTI)
|
||||
@ -165,25 +165,9 @@ struct TAny
|
||||
&& (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value
|
||||
&& TIsConstructible<typename TDecay<T>::Type, Types...>::Value
|
||||
explicit TAny(TInPlaceType<T>, Types&&... Args)
|
||||
: TypeInfo(Typeid(typename TDecay<T>::Type))
|
||||
{
|
||||
using SelectedType = typename TDecay<T>::Type;
|
||||
|
||||
if constexpr (TIsTriviallyStorable<SelectedType>::Value)
|
||||
{
|
||||
new(&InlineValue) SelectedType(Forward<Types>(Args)...);
|
||||
RTTI = nullptr;
|
||||
}
|
||||
else if constexpr (TIsInlineStorable<SelectedType>::Value)
|
||||
{
|
||||
new(&InlineValue) SelectedType(Forward<Types>(Args)...);
|
||||
RTTI = &NAMESPACE_PRIVATE::TAnyRTTIHelper<SelectedType, true>::RTTI;
|
||||
}
|
||||
else
|
||||
{
|
||||
DynamicValue = new SelectedType(Forward<Types>(Args)...);
|
||||
RTTI = &NAMESPACE_PRIVATE::TAnyRTTIHelper<SelectedType, false>::RTTI;
|
||||
}
|
||||
EmplaceImpl<SelectedType>(Forward<Types>(Args)...);
|
||||
}
|
||||
|
||||
template <typename T> requires (!TIsSame<typename TDecay<T>::Type, TAny>::Value) && (!TIsTInPlaceType<typename TDecay<T>::Type>::Value)
|
||||
@ -199,6 +183,8 @@ struct TAny
|
||||
|
||||
TAny& operator=(const TAny& InValue)
|
||||
{
|
||||
if (&InValue == this) return *this;
|
||||
|
||||
if (!InValue.IsValid())
|
||||
{
|
||||
Reset();
|
||||
@ -225,6 +211,8 @@ struct TAny
|
||||
|
||||
TAny& operator=(TAny&& InValue)
|
||||
{
|
||||
if (&InValue == this) return *this;
|
||||
|
||||
if (!InValue.IsValid())
|
||||
{
|
||||
Reset();
|
||||
@ -271,24 +259,7 @@ struct TAny
|
||||
else
|
||||
{
|
||||
Reset();
|
||||
|
||||
TypeInfo = Typeid(SelectedType);
|
||||
|
||||
if constexpr (TIsTriviallyStorable<SelectedType>::Value)
|
||||
{
|
||||
new(&InlineValue) SelectedType(Forward<T>(InValue));
|
||||
RTTI = nullptr;
|
||||
}
|
||||
else if constexpr (TIsInlineStorable<SelectedType>::Value)
|
||||
{
|
||||
new(&InlineValue) SelectedType(Forward<T>(InValue));
|
||||
RTTI = &NAMESPACE_PRIVATE::TAnyRTTIHelper<SelectedType, true>::RTTI;
|
||||
}
|
||||
else
|
||||
{
|
||||
DynamicValue = new SelectedType(Forward<T>(InValue));
|
||||
RTTI = &NAMESPACE_PRIVATE::TAnyRTTIHelper<SelectedType, false>::RTTI;
|
||||
}
|
||||
EmplaceImpl<SelectedType>(Forward<T>(InValue));
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -302,33 +273,15 @@ struct TAny
|
||||
Reset();
|
||||
|
||||
using SelectedType = typename TDecay<T>::Type;
|
||||
|
||||
TypeInfo = Typeid(SelectedType);
|
||||
|
||||
if constexpr (TIsTriviallyStorable<SelectedType>::Value)
|
||||
{
|
||||
new(&InlineValue) SelectedType(Forward<Types>(Args)...);
|
||||
RTTI = nullptr;
|
||||
}
|
||||
else if constexpr (TIsInlineStorable<SelectedType>::Value)
|
||||
{
|
||||
new(&InlineValue) SelectedType(Forward<Types>(Args)...);
|
||||
RTTI = &NAMESPACE_PRIVATE::TAnyRTTIHelper<SelectedType, true>::RTTI;
|
||||
}
|
||||
else
|
||||
{
|
||||
DynamicValue = new SelectedType(Forward<Types>(Args)...);
|
||||
RTTI = &NAMESPACE_PRIVATE::TAnyRTTIHelper<SelectedType, false>::RTTI;
|
||||
}
|
||||
|
||||
EmplaceImpl<SelectedType>(Forward<Types>(Args)...);
|
||||
return GetValue<SelectedType>();
|
||||
}
|
||||
|
||||
constexpr FTypeInfo GetTypeInfo() const { return TypeInfo; }
|
||||
constexpr bool IsValid() const { return TypeInfo != Typeid(void); }
|
||||
constexpr explicit operator bool() const { return TypeInfo != Typeid(void); }
|
||||
constexpr bool IsInline() const { return RTTI != nullptr ? RTTI->bIsInline : true; }
|
||||
constexpr bool IsTrivial() const { return RTTI == nullptr; }
|
||||
constexpr FTypeInfo GetTypeInfo() const { return TypeInfo; }
|
||||
constexpr bool IsValid() const { return TypeInfo != Typeid(void); }
|
||||
constexpr explicit operator bool() const { return TypeInfo != Typeid(void); }
|
||||
constexpr bool IsInline() const { return RTTI != nullptr ? RTTI->bIsInline : true; }
|
||||
constexpr bool IsTrivial() const { return RTTI == nullptr; }
|
||||
|
||||
template <typename T> constexpr bool HoldsAlternative() const { return IsValid() ? TypeInfo == Typeid(T) : false; }
|
||||
|
||||
@ -377,6 +330,28 @@ private:
|
||||
FTypeInfo TypeInfo;
|
||||
const NAMESPACE_PRIVATE::FAnyRTTI* RTTI;
|
||||
|
||||
template <typename SelectedType, typename... Types>
|
||||
void EmplaceImpl(Types&&... Args)
|
||||
{
|
||||
TypeInfo = Typeid(SelectedType);
|
||||
|
||||
if constexpr (TIsTriviallyStorable<SelectedType>::Value)
|
||||
{
|
||||
new(&InlineValue) SelectedType(Forward<Types>(Args)...);
|
||||
RTTI = nullptr;
|
||||
}
|
||||
else if constexpr (TIsInlineStorable<SelectedType>::Value)
|
||||
{
|
||||
new(&InlineValue) SelectedType(Forward<Types>(Args)...);
|
||||
RTTI = &NAMESPACE_PRIVATE::TAnyRTTIHelper<SelectedType, true>::RTTI;
|
||||
}
|
||||
else
|
||||
{
|
||||
DynamicValue = new SelectedType(Forward<Types>(Args)...);
|
||||
RTTI = &NAMESPACE_PRIVATE::TAnyRTTIHelper<SelectedType, false>::RTTI;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename T, size_t InlineSize, size_t InlineAlignment>
|
||||
@ -385,48 +360,12 @@ constexpr bool operator==(const TAny<InlineSize, InlineAlignment>& LHS, const T&
|
||||
return LHS.template HoldsAlternative<T>() ? LHS.template GetValue<T>() == RHS : false;
|
||||
}
|
||||
|
||||
template <typename T, size_t InlineSize, size_t InlineAlignment>
|
||||
constexpr bool operator!=(const TAny<InlineSize, InlineAlignment>& LHS, const T& RHS)
|
||||
{
|
||||
return LHS.template HoldsAlternative<T>() ? LHS.template GetValue<T>() != RHS : true;
|
||||
}
|
||||
|
||||
template <typename T, size_t InlineSize, size_t InlineAlignment>
|
||||
constexpr bool operator==(const T& LHS, const TAny<InlineSize, InlineAlignment>& RHS)
|
||||
{
|
||||
return RHS.template HoldsAlternative<T>() ? LHS == RHS.template GetValue<T>() : false;
|
||||
}
|
||||
|
||||
template <typename T, size_t InlineSize, size_t InlineAlignment>
|
||||
constexpr bool operator!=(const T& LHS, const TAny<InlineSize, InlineAlignment>& RHS)
|
||||
{
|
||||
return RHS.template HoldsAlternative<T>() ? LHS != RHS.template GetValue<T>() : true;
|
||||
}
|
||||
|
||||
template <size_t InlineSize, size_t InlineAlignment>
|
||||
constexpr bool operator==(const TAny<InlineSize, InlineAlignment>& LHS, FInvalid)
|
||||
{
|
||||
return !LHS.IsValid();
|
||||
}
|
||||
|
||||
template <size_t InlineSize, size_t InlineAlignment>
|
||||
constexpr bool operator!=(const TAny<InlineSize, InlineAlignment>& LHS, FInvalid)
|
||||
{
|
||||
return LHS.IsValid();
|
||||
}
|
||||
|
||||
template <size_t InlineSize, size_t InlineAlignment>
|
||||
constexpr bool operator==(FInvalid, const TAny<InlineSize, InlineAlignment>& RHS)
|
||||
{
|
||||
return !RHS.IsValid();
|
||||
}
|
||||
|
||||
template <size_t InlineSize, size_t InlineAlignment>
|
||||
constexpr bool operator!=(FInvalid, const TAny<InlineSize, InlineAlignment>& RHS)
|
||||
{
|
||||
return RHS.IsValid();
|
||||
}
|
||||
|
||||
template <size_t InlineSize, size_t InlineAlignment>
|
||||
constexpr void Swap(TAny<InlineSize, InlineAlignment>& A, TAny<InlineSize, InlineAlignment>& B)
|
||||
{
|
||||
|
@ -106,9 +106,11 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T = OptionalType> requires TIsConstructible<OptionalType, const T&>::Value
|
||||
template <typename T = OptionalType> requires TIsConstructible<OptionalType, const T&>::Value && TIsAssignable<OptionalType, const T&>::Value
|
||||
constexpr TOptional& operator=(const TOptional<T>& InValue)
|
||||
{
|
||||
if (&InValue == this) return *this;
|
||||
|
||||
if (!InValue.IsValid())
|
||||
{
|
||||
Reset();
|
||||
@ -125,9 +127,11 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T = OptionalType> requires TIsConstructible<OptionalType, T&&>::Value
|
||||
template <typename T = OptionalType> requires TIsConstructible<OptionalType, T&&>::Value && TIsAssignable<OptionalType, T&&>::Value
|
||||
constexpr TOptional& operator=(TOptional<T>&& InValue)
|
||||
{
|
||||
if (&InValue == this) return *this;
|
||||
|
||||
if (!InValue.IsValid())
|
||||
{
|
||||
Reset();
|
||||
@ -144,7 +148,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T = OptionalType> requires TIsConstructible<OptionalType, T&&>::Value
|
||||
template <typename T = OptionalType> requires TIsConstructible<OptionalType, T&&>::Value && TIsAssignable<OptionalType, T&&>::Value
|
||||
constexpr TOptional& operator=(T&& InValue)
|
||||
{
|
||||
if (IsValid()) GetValue() = Forward<T>(InValue);
|
||||
@ -157,12 +161,12 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... ArgsType>
|
||||
constexpr OptionalType& Emplace(ArgsType&&... Args)
|
||||
template <typename... ArgTypes> requires TIsConstructible<OptionalType, ArgTypes...>::Value
|
||||
constexpr OptionalType& Emplace(ArgTypes&&... Args)
|
||||
{
|
||||
Reset();
|
||||
|
||||
OptionalType* Result = new(&Value) OptionalType(Forward<ArgsType>(Args)...);
|
||||
OptionalType* Result = new(&Value) OptionalType(Forward<ArgTypes>(Args)...);
|
||||
bIsValid = true;
|
||||
|
||||
return *Result;
|
||||
@ -225,62 +229,18 @@ constexpr bool operator==(const TOptional<T>& LHS, const TOptional<U>& RHS)
|
||||
return *LHS == *RHS;
|
||||
}
|
||||
|
||||
template <typename T, typename U> requires CWeaklyEqualityComparableWith<T, U>
|
||||
constexpr bool operator!=(const TOptional<T>& LHS, const TOptional<U>& RHS)
|
||||
{
|
||||
if (LHS.IsValid() != RHS.IsValid()) return true;
|
||||
if (LHS.IsValid() == false) return false;
|
||||
return *LHS != *RHS;
|
||||
}
|
||||
|
||||
template <typename T, typename U> requires CWeaklyEqualityComparableWith<T, U>
|
||||
constexpr bool operator==(const TOptional<T>& LHS, const U& RHS)
|
||||
{
|
||||
return LHS.IsValid() ? *LHS == RHS : false;
|
||||
}
|
||||
|
||||
template <typename T, typename U> requires CWeaklyEqualityComparableWith<T, U>
|
||||
constexpr bool operator!=(const TOptional<T>& LHS, const U& RHS)
|
||||
{
|
||||
return LHS.IsValid() ? *LHS != RHS : true;
|
||||
}
|
||||
|
||||
template <typename T, typename U> requires CWeaklyEqualityComparableWith<T, U>
|
||||
constexpr bool operator==(const T& LHS, const TOptional<U>& RHS)
|
||||
{
|
||||
return RHS.IsValid() ? LHS == *RHS : false;
|
||||
}
|
||||
|
||||
template <typename T, typename U> requires CWeaklyEqualityComparableWith<T, U>
|
||||
constexpr bool operator!=(const T& LHS, const TOptional<U>& RHS)
|
||||
{
|
||||
return RHS.IsValid() ? LHS != *RHS : true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool operator==(const TOptional<T>& LHS, FInvalid)
|
||||
{
|
||||
return !LHS.IsValid();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool operator!=(const TOptional<T>& LHS, FInvalid)
|
||||
{
|
||||
return LHS.IsValid();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool operator==(FInvalid, const TOptional<T>& RHS)
|
||||
{
|
||||
return !RHS.IsValid();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool operator!=(FInvalid, const TOptional<T>& RHS)
|
||||
{
|
||||
return RHS.IsValid();
|
||||
}
|
||||
|
||||
template <typename T> requires (TIsObject<T>::Value && !TIsArray<T>::Value && TIsDestructible<T>::Value)
|
||||
constexpr TOptional<typename TDecay<T>::Type> MakeOptional(FInvalid)
|
||||
{
|
||||
|
@ -132,16 +132,6 @@ constexpr bool VariantEqualityOperator(const void* LHS, const void* RHS)
|
||||
|
||||
using FVariantEqualityOperatorFunc = bool(*)(const void*, const void*);
|
||||
|
||||
template <typename T>
|
||||
constexpr bool VariantInequalityOperator(const void* LHS, const void* RHS)
|
||||
{
|
||||
if constexpr (!CEqualityComparable<T>) check_no_entry();
|
||||
else return *reinterpret_cast<const T*>(LHS) != *reinterpret_cast<const T*>(RHS);
|
||||
return false;
|
||||
}
|
||||
|
||||
using FVariantInequalityOperatorFunc = bool(*)(const void*, const void*);
|
||||
|
||||
template <typename... Types>
|
||||
struct TVariantHelper
|
||||
{
|
||||
@ -151,7 +141,6 @@ struct TVariantHelper
|
||||
static constexpr FVariantCopyAssignFunc CopyAssignFuncs[] = { VariantCopyAssign<Types>... };
|
||||
static constexpr FVariantMoveAssignFunc MoveAssignFuncs[] = { VariantMoveAssign<Types>... };
|
||||
static constexpr FVariantEqualityOperatorFunc EqualityOperatorFuncs[] = { VariantEqualityOperator<Types>... };
|
||||
static constexpr FVariantInequalityOperatorFunc InequalityOperatorFuncs[] = { VariantInequalityOperator<Types>... };
|
||||
};
|
||||
|
||||
template <typename R, typename F, typename T>
|
||||
@ -451,13 +440,6 @@ private:
|
||||
return FHelper::EqualityOperatorFuncs[LHS.GetIndex()](&LHS.Value, &RHS.Value);
|
||||
}
|
||||
|
||||
friend constexpr bool operator!=(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CEqualityComparable<Types>)
|
||||
{
|
||||
if (LHS.GetIndex() != RHS.GetIndex()) return true;
|
||||
if (LHS.IsValid() == false) return false;
|
||||
return FHelper::InequalityOperatorFuncs[LHS.GetIndex()](&LHS.Value, &RHS.Value);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename T, typename... Types> requires (!TIsSame<T, TVariant<Types...>>::Value) && CEqualityComparable<T>
|
||||
@ -466,48 +448,12 @@ constexpr bool operator==(const TVariant<Types...>& LHS, const T& RHS)
|
||||
return LHS.template HoldsAlternative<T>() ? LHS.template GetValue<T>() == RHS : false;
|
||||
}
|
||||
|
||||
template <typename T, typename... Types> requires (!TIsSame<T, TVariant<Types...>>::Value) && CEqualityComparable<T>
|
||||
constexpr bool operator!=(const TVariant<Types...>& LHS, const T& RHS)
|
||||
{
|
||||
return LHS.template HoldsAlternative<T>() ? LHS.template GetValue<T>() != RHS : true;
|
||||
}
|
||||
|
||||
template <typename T, typename... Types> requires (!TIsSame<T, TVariant<Types...>>::Value) && CEqualityComparable<T>
|
||||
constexpr bool operator==(const T& LHS, const TVariant<Types...>& RHS)
|
||||
{
|
||||
return RHS.template HoldsAlternative<T>() ? LHS == RHS.template GetValue<T>() : false;
|
||||
}
|
||||
|
||||
template <typename T, typename... Types> requires (!TIsSame<T, TVariant<Types...>>::Value) && CEqualityComparable<T>
|
||||
constexpr bool operator!=(const T& LHS, const TVariant<Types...>& RHS)
|
||||
{
|
||||
return RHS.template HoldsAlternative<T>() ? LHS != RHS.template GetValue<T>() : true;
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
constexpr bool operator==(const TVariant<Types...>& LHS, FInvalid)
|
||||
{
|
||||
return !LHS.IsValid();
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
constexpr bool operator!=(const TVariant<Types...>& LHS, FInvalid)
|
||||
{
|
||||
return LHS.IsValid();
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
constexpr bool operator==(FInvalid, const TVariant<Types...>& RHS)
|
||||
{
|
||||
return !RHS.IsValid();
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
constexpr bool operator!=(FInvalid, const TVariant<Types...>& RHS)
|
||||
{
|
||||
return RHS.IsValid();
|
||||
}
|
||||
|
||||
template <typename... Types> requires (true && ... && (TIsMoveConstructible<Types>::Value && TIsSwappable<Types>::Value))
|
||||
constexpr void Swap(TVariant<Types...>& A, TVariant<Types...>& B)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user