From c2eca8df1e495098d5ed7476603669fbb7508bea Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Sun, 24 Apr 2022 22:42:40 +0800 Subject: [PATCH] refactor(templates): remove the GetData function from the non-container class --- .../Source/Public/Templates/Any.h | 80 ++++++------ .../Source/Public/Templates/Function.h | 123 +++++++----------- .../Source/Public/Templates/Optional.h | 3 - .../Source/Public/Templates/Tuple.h | 3 - .../Source/Public/Templates/Variant.h | 5 +- 5 files changed, 85 insertions(+), 129 deletions(-) diff --git a/Redcraft.Utility/Source/Public/Templates/Any.h b/Redcraft.Utility/Source/Public/Templates/Any.h index cf0f37e..ec8c191 100644 --- a/Redcraft.Utility/Source/Public/Templates/Any.h +++ b/Redcraft.Utility/Source/Public/Templates/Any.h @@ -179,9 +179,9 @@ struct TAny { if (!IsValid()) return; - if (IsTrivial()) Memory::Memcpy(InlineValue, InValue.InlineValue); - else if (IsInline()) RTTI->CopyConstruct(GetData(), InValue.GetData()); - else DynamicValue = RTTI->CopyNew(InValue.GetData()); + if (IsTrivial()) Memory::Memcpy(InlineStorage, InValue.InlineStorage); + else if (IsInline()) RTTI->CopyConstruct(GetStorage(), InValue.GetStorage()); + else DynamicStorage = RTTI->CopyNew(InValue.GetStorage()); } FORCEINLINE TAny(TAny&& InValue) @@ -189,11 +189,11 @@ struct TAny { if (!IsValid()) return; - if (IsTrivial()) Memory::Memcpy(InlineValue, InValue.InlineValue); - else if (IsInline()) RTTI->MoveConstruct(GetData(), InValue.GetData()); + if (IsTrivial()) Memory::Memcpy(InlineStorage, InValue.InlineStorage); + else if (IsInline()) RTTI->MoveConstruct(GetStorage(), InValue.GetStorage()); else { - DynamicValue = InValue.DynamicValue; + DynamicStorage = InValue.DynamicStorage; InValue.TypeInfo = nullptr; } } @@ -228,8 +228,8 @@ struct TAny } else if (GetTypeInfo() == InValue.GetTypeInfo()) { - if (IsTrivial()) Memory::Memcpy(InlineValue, InValue.InlineValue); - else RTTI->CopyAssign(GetData(), InValue.GetData()); + if (IsTrivial()) Memory::Memcpy(InlineStorage, InValue.InlineStorage); + else RTTI->CopyAssign(GetStorage(), InValue.GetStorage()); } else { @@ -238,9 +238,9 @@ struct TAny TypeInfo = InValue.TypeInfo; RTTI = InValue.RTTI; - if (IsTrivial()) Memory::Memcpy(InlineValue, InValue.InlineValue); - else if (IsInline()) RTTI->CopyConstruct(GetData(), InValue.GetData()); - else DynamicValue = RTTI->CopyNew(InValue.GetData()); + if (IsTrivial()) Memory::Memcpy(InlineStorage, InValue.InlineStorage); + else if (IsInline()) RTTI->CopyConstruct(GetStorage(), InValue.GetStorage()); + else DynamicStorage = RTTI->CopyNew(InValue.GetStorage()); } return *this; @@ -256,12 +256,12 @@ struct TAny } else if (GetTypeInfo() == InValue.GetTypeInfo()) { - if (IsTrivial()) Memory::Memcpy(InlineValue, InValue.InlineValue); - else if (IsInline()) RTTI->MoveAssign(GetData(), InValue.GetData()); + if (IsTrivial()) Memory::Memcpy(InlineStorage, InValue.InlineStorage); + else if (IsInline()) RTTI->MoveAssign(GetStorage(), InValue.GetStorage()); else { - RTTI->Delete(DynamicValue); - DynamicValue = InValue.DynamicValue; + RTTI->Delete(DynamicStorage); + DynamicStorage = InValue.DynamicStorage; InValue.TypeInfo = nullptr; } } @@ -272,9 +272,9 @@ struct TAny TypeInfo = InValue.TypeInfo; RTTI = InValue.RTTI; - if (IsTrivial()) Memory::Memcpy(InlineValue, InValue.InlineValue); - else if (IsInline()) RTTI->MoveConstruct(GetData(), InValue.GetData()); - else DynamicValue = RTTI->MoveNew(InValue.GetData()); + if (IsTrivial()) Memory::Memcpy(InlineStorage, InValue.InlineStorage); + else if (IsInline()) RTTI->MoveConstruct(GetStorage(), InValue.GetStorage()); + else DynamicStorage = RTTI->MoveNew(InValue.GetStorage()); } return *this; @@ -290,7 +290,7 @@ struct TAny if (HoldsAlternative()) { if constexpr (TIsTriviallyStorable::Value) - Memory::Memcpy(&InlineValue, &InValue, sizeof(SelectedType)); + Memory::Memcpy(&InlineStorage, &InValue, sizeof(SelectedType)); else GetValue() = Forward(InValue); } else @@ -323,20 +323,17 @@ struct TAny template constexpr bool HoldsAlternative() const { return IsValid() ? GetTypeInfo() == Typeid(T) : false; } - constexpr void* GetData() { return IsInline() ? &InlineValue : DynamicValue; } - constexpr const void* GetData() const { return IsInline() ? &InlineValue : DynamicValue; } + 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*>(GetStorage()); } 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()); } + 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*>(GetStorage())); } 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())); } + 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(GetStorage()); } 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())); } + 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(GetStorage())); } template requires TIsSame::Type>::Value&& TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value constexpr T& Get( T& DefaultValue) & { return HoldsAlternative() ? GetValue() : DefaultValue; } @@ -350,13 +347,13 @@ struct TAny ResetImpl(); } -// constexpr size_t GetTypeHash() const +// FORCEINLINE size_t GetTypeHash() const // { // if (!IsValid()) return 20090007; -// return HashCombine(NAMESPACE_REDCRAFT::GetTypeHash(GetTypeInfo()), RTTI->TypeHash(GetData())); +// return HashCombine(NAMESPACE_REDCRAFT::GetTypeHash(GetTypeInfo()), RTTI->TypeHash(GetStorage())); // } // -// constexpr void Swap(TAny& InValue) +// FORCEINLINE void Swap(TAny& InValue) // { // if (!IsValid() && !InValue.IsValid()) return; // @@ -376,7 +373,7 @@ struct TAny // // if (GetTypeInfo() == InValue.GetTypeInfo()) // { -// RTTI->SwapObject(GetData(), InValue.GetData()); +// RTTI->SwapObject(GetStorage(), InValue.GetStorage()); // return; // } // @@ -389,13 +386,16 @@ private: union { - TAlignedStorage::Type InlineValue; - void* DynamicValue; + TAlignedStorage::Type InlineStorage; + void* DynamicStorage; }; const FTypeInfo* TypeInfo; const NAMESPACE_PRIVATE::FAnyRTTI* RTTI; - + + constexpr void* GetStorage() { return IsInline() ? &InlineStorage : DynamicStorage; } + constexpr const void* GetStorage() const { return IsInline() ? &InlineStorage : DynamicStorage; } + template FORCEINLINE void EmplaceImpl(Types&&... Args) { @@ -403,17 +403,17 @@ private: if constexpr (TIsTriviallyStorable::Value) { - new(&InlineValue) SelectedType(Forward(Args)...); + new(&InlineStorage) SelectedType(Forward(Args)...); RTTI = nullptr; } else if constexpr (TIsInlineStorable::Value) { - new(&InlineValue) SelectedType(Forward(Args)...); + new(&InlineStorage) SelectedType(Forward(Args)...); RTTI = &NAMESPACE_PRIVATE::TAnyRTTIHelper::RTTI; } else { - DynamicValue = new SelectedType(Forward(Args)...); + DynamicStorage = new SelectedType(Forward(Args)...); RTTI = &NAMESPACE_PRIVATE::TAnyRTTIHelper::RTTI; } } @@ -421,15 +421,15 @@ private: FORCEINLINE void ResetImpl() { if (!IsValid() || IsTrivial()) return; - else if (IsInline()) RTTI->Destroy(&InlineValue); - else RTTI->Delete(DynamicValue); + else if (IsInline()) RTTI->Destroy(&InlineStorage); + else RTTI->Delete(DynamicStorage); } // friend FORCEINLINE bool operator==(const TAny& LHS, const TAny& RHS) // { // if (LHS.GetTypeInfo() != RHS.GetTypeInfo()) return false; // if (LHS.IsValid() == false) return true; -// return LHS.RTTI->EqualityOperator(LHS.GetData(), RHS.GetData()); +// return LHS.RTTI->EqualityOperator(LHS.GetStorage(), RHS.GetStorage()); // } }; diff --git a/Redcraft.Utility/Source/Public/Templates/Function.h b/Redcraft.Utility/Source/Public/Templates/Function.h index 8647c48..ae0f4d6 100644 --- a/Redcraft.Utility/Source/Public/Templates/Function.h +++ b/Redcraft.Utility/Source/Public/Templates/Function.h @@ -54,7 +54,7 @@ template struct TIsTFunc template struct TIsTUniqueFunction : FFalse { }; template struct TIsTUniqueFunction> : FTrue { }; -struct FFunctionIsBoundImpl +struct FFunctionIsBound { template static constexpr bool F(const T& Func) @@ -95,62 +95,13 @@ struct TIsInvocableResultWithSpecifiers struct TIsInvocableResultWithSpecifiers : TIsInvocableResult { }; -template -struct TFunctionCallImpl; - -template -struct TFunctionCallImpl -{ - static inline R F(void* Func, Types&&... Args) - { - return InvokeResult(*reinterpret_cast(Func), Forward(Args)...); - } -}; - -template -struct TFunctionCallImpl -{ - static inline R F(void* Func, Types&&... Args) - { - return InvokeResult(*reinterpret_cast(Func), Forward(Args)...); - } -}; - -template -struct TFunctionCallImpl -{ - static inline R F(void* Func, Types&&... Args) - { - return InvokeResult(MoveTemp(*reinterpret_cast(Func)), Forward(Args)...); - } -}; - -template -struct TFunctionCallImpl -{ - static inline R F(void* Func, Types&&... Args) - { - return InvokeResult(AsConst(*reinterpret_cast(Func)), Forward(Args)...); - } -}; - -template -struct TFunctionCallImpl -{ - static inline R F(void* Func, Types&&... Args) - { - return InvokeResult(AsConst(*reinterpret_cast(Func)), Forward(Args)...); - } -}; - -template -struct TFunctionCallImpl -{ - static inline R F(void* Func, Types&&... Args) - { - return InvokeResult(MoveTemp(AsConst(*reinterpret_cast(Func))), Forward(Args)...); - } -}; +template struct TFunctionCallSpecifiers; +template struct TFunctionCallSpecifiers { using Type = T& ; }; +template struct TFunctionCallSpecifiers { using Type = T& ; }; +template struct TFunctionCallSpecifiers { using Type = T&&; }; +template struct TFunctionCallSpecifiers { using Type = const T& ; }; +template struct TFunctionCallSpecifiers { using Type = const T& ; }; +template struct TFunctionCallSpecifiers { using Type = const T&&; }; template struct TFunctionImpl @@ -160,14 +111,14 @@ public: using ResultType = R; using ArgumentType = TTuple; - constexpr TFunctionImpl(nullptr_t = nullptr) requires (FunctionType != EFunctionType::Reference) : Call(nullptr) { } + constexpr TFunctionImpl(nullptr_t = nullptr) requires (FunctionType != EFunctionType::Reference) : Callable(nullptr) { } TFunctionImpl(const TFunctionImpl& InValue) requires (FunctionType != EFunctionType::Unique) - : Call(InValue.Call), Storage(InValue.Storage) + : Callable(InValue.Callable), Storage(InValue.Storage) { } TFunctionImpl(TFunctionImpl&& InValue) - : Call(InValue.Call), Storage(MoveTemp(InValue.Storage)) + : Callable(InValue.Callable), Storage(MoveTemp(InValue.Storage)) { if constexpr (FunctionType != EFunctionType::Reference) InValue.Reset(); } template requires (!TIsTFunctionImpl::Type>::Value) && (!TIsTInPlaceType::Type>::Value) @@ -182,10 +133,10 @@ public: if constexpr (FunctionType == EFunctionType::Reference) { - checkf(FFunctionIsBoundImpl::F(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef")); + checkf(FFunctionIsBound::F(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef")); } - if (!FFunctionIsBoundImpl::F(InValue)) Call = nullptr; + if (!FFunctionIsBound::F(InValue)) Callable = nullptr; else EmplaceImpl(Forward(InValue)); } @@ -203,16 +154,16 @@ public: requires (FunctionType == EFunctionType::Reference) && (OtherFunctionType != EFunctionType::Reference) FORCEINLINE TFunctionImpl(const TFunctionImpl& InValue) { - checkf(FFunctionIsBoundImpl::F(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef")); + checkf(FFunctionIsBound::F(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef")); EmplaceImpl>(InValue); } FORCEINLINE TFunctionImpl(const TFunctionImpl& InValue) requires (FunctionType == EFunctionType::Unique) - : Call((*reinterpret_cast(&InValue)).Call), Storage((*reinterpret_cast(&InValue)).Storage) + : Callable((*reinterpret_cast(&InValue)).Callable), Storage((*reinterpret_cast(&InValue)).Storage) { } FORCEINLINE TFunctionImpl(TFunctionImpl&& InValue) requires (FunctionType == EFunctionType::Unique) - : Call((*reinterpret_cast(&InValue)).Call), Storage(MoveTemp((*reinterpret_cast(&InValue)).Storage)) + : Callable((*reinterpret_cast(&InValue)).Callable), Storage(MoveTemp((*reinterpret_cast(&InValue)).Storage)) { InValue.Reset(); } ~TFunctionImpl() = default; @@ -253,7 +204,7 @@ public: { using DecayedFunctorType = typename TDecay::Type; - if (!FFunctionIsBoundImpl::F(InValue)) Reset(); + if (!FFunctionIsBound::F(InValue)) Reset(); else EmplaceImpl(Forward(InValue)); return *this; @@ -278,11 +229,8 @@ public: FORCEINLINE ResultType operator()(Types... Args) const& requires (Specifiers == EFunctionSpecifiers::ConstLValue) { return CallImpl(Forward(Args)...); } FORCEINLINE ResultType operator()(Types... Args) const&& requires (Specifiers == EFunctionSpecifiers::ConstRValue) { return CallImpl(Forward(Args)...); } - constexpr bool IsValid() const { return Call != nullptr; } - constexpr explicit operator bool() const { return Call != nullptr; } - - FORCEINLINE void* GetData() { if constexpr (FunctionType != EFunctionType::Reference) return Storage.GetData(); else return Storage; } - FORCEINLINE const void* GetData() const { if constexpr (FunctionType != EFunctionType::Reference) return Storage.GetData(); else return Storage; } + constexpr bool IsValid() const { return Callable != nullptr; } + constexpr explicit operator bool() const { return Callable != nullptr; } FORCEINLINE const FTypeInfo& TargetType() const requires (FunctionType != EFunctionType::Reference) { return IsValid() ? Storage.GetTypeInfo() : Typeid(void); }; @@ -291,7 +239,7 @@ public: template FORCEINLINE const T& Target() const& requires (FunctionType != EFunctionType::Reference) && TIsSame::Type>::Value && TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value { return static_cast(Storage).template GetValue(); } template FORCEINLINE const T&& Target() const&& requires (FunctionType != EFunctionType::Reference) && TIsSame::Type>::Value && TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value { return static_cast(Storage).template GetValue(); } - constexpr void Reset() requires (FunctionType != EFunctionType::Reference) { Call = nullptr; } + constexpr void Reset() requires (FunctionType != EFunctionType::Reference) { Callable = nullptr; } constexpr void Swap(TFunctionImpl& InValue) requires (FunctionType != EFunctionType::Reference) { @@ -311,37 +259,54 @@ public: return; } - NAMESPACE_REDCRAFT::Swap(Call, InValue.Call); + NAMESPACE_REDCRAFT::Swap(Callable, InValue.Callable); NAMESPACE_REDCRAFT::Swap(Storage, InValue.Storage); } private: - using CallFunc = ResultType(*)(void*, Types&&...); using StorageType = typename TConditional>::Type; + using StorageRef = typename TConditional::Type&>::Type; + using CallFunc = ResultType(*)(StorageRef, Types&&...); - CallFunc Call; StorageType Storage; + CallFunc Callable; template FORCEINLINE void EmplaceImpl(ArgTypes&&... Args) { if constexpr (FunctionType == EFunctionType::Reference) Storage = ((void*)&Args, ...); else Storage.template Emplace(Forward(Args)...); - Call = &TFunctionCallImpl::F; + + Callable = [](StorageRef Storage, Types&&... Args) -> ResultType + { + const auto GetFunc = [&Storage]() -> decltype(auto) + { + if constexpr (FunctionType == EFunctionType::Reference) return *reinterpret_cast(Storage); + else return Storage.template GetValue(); + }; + + return InvokeResult(Forward::Type>(GetFunc()), Forward(Args)...); + }; + } + + FORCEINLINE ResultType CallImpl(Types&&... Args) + { + checkf(IsValid(), TEXT("Attempting to call an unbound TFunction!")); + return Callable(Storage, Forward(Args)...); } FORCEINLINE ResultType CallImpl(Types&&... Args) const { checkf(IsValid(), TEXT("Attempting to call an unbound TFunction!")); - return Call(const_cast(*this).GetData(), Forward(Args)...); + return Callable(Storage, Forward(Args)...); } FORCEINLINE void AssignImpl(const TFunctionImpl& InValue) { if (InValue.IsValid()) { - Call = InValue.Call; + Callable = InValue.Callable; Storage = InValue.Storage; } else Reset(); @@ -351,7 +316,7 @@ private: { if (InValue.IsValid()) { - Call = InValue.Call; + Callable = InValue.Callable; Storage = MoveTemp(InValue.Storage); InValue.Reset(); } diff --git a/Redcraft.Utility/Source/Public/Templates/Optional.h b/Redcraft.Utility/Source/Public/Templates/Optional.h index f235a61..dfc3634 100644 --- a/Redcraft.Utility/Source/Public/Templates/Optional.h +++ b/Redcraft.Utility/Source/Public/Templates/Optional.h @@ -189,9 +189,6 @@ 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 *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); } diff --git a/Redcraft.Utility/Source/Public/Templates/Tuple.h b/Redcraft.Utility/Source/Public/Templates/Tuple.h index 36a582d..c2cc9fd 100644 --- a/Redcraft.Utility/Source/Public/Templates/Tuple.h +++ b/Redcraft.Utility/Source/Public/Templates/Tuple.h @@ -308,9 +308,6 @@ public: TTuple& operator=(const TTuple&) = default; TTuple& operator=(TTuple&&) = default; - constexpr void* GetData() { return this; } - constexpr const void* GetData() const { return this; } - 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(); } diff --git a/Redcraft.Utility/Source/Public/Templates/Variant.h b/Redcraft.Utility/Source/Public/Templates/Variant.h index 893f738..62725b5 100644 --- a/Redcraft.Utility/Source/Public/Templates/Variant.h +++ b/Redcraft.Utility/Source/Public/Templates/Variant.h @@ -338,9 +338,6 @@ struct TVariant template constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == I : false; } template constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == TAlternativeIndex::Value : false; } - - constexpr void* GetData() { return &Value; } - constexpr const void* GetData() const { return &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)); } @@ -456,7 +453,7 @@ struct TVariant if (GetIndex() == InValue.GetIndex()) { - FHelper::SwapFuncs[GetIndex()](GetData(), InValue.GetData()); + FHelper::SwapFuncs[GetIndex()](&Value, &InValue.Value); return; }