Compile time optimizations Managed to reduce unnamed game's biggest file compiler frontend cost from 113 seconds to 60 seconds. This also impact other things such as pch size and memory footprint when compiling which is great.

Takeaways. Try to use "friend" on functions/operators that are frequently overloaded EXCEPT if they are in a templated type that is frequently instantiated. So do not put friends in TMap, TSet, TObjectPtr etc, this will slow down compile times. There is a break-even somewhere and hard to tell where it is but taking a class that is templatized on character type probably don't matter either way and then it is nicer to use a friend since that simplies error messages when compiler can't resolve functions/operators.

If it is possible to use member functions instead of friend that is the best option in terms of compile time performance. With c++20 you only have to write operator==(Foo, Bar) and the compiler will automatically provide operator==(Bar, Foo), operator!=(Foo, Bar) and operator!=(Bar, Foo).

Changes in this changelist involes
* Making operator<< friends in non-template types and not friends in template types
* Making operator==/!= members where possible and if not possible moved out if type is a frequently instantiated templated type.

#preflight 636970f5376a9cd6a80da54a
#rb steve.robb

[CL 23038965 by henrik karlsson in ue5-main branch]
This commit is contained in:
henrik karlsson
2022-11-08 15:59:46 -05:00
parent 22cb6cec34
commit 4feb09e0b3
68 changed files with 1962 additions and 1627 deletions
@@ -37,21 +37,21 @@ public:
virtual FString GetArchiveName() const { return TEXT("FArchiveCrc32"); }
//~ End FArchive Interface
/**
* Serializes a USTRUCT value from or into an archive.
*
* @param Ar The archive to serialize from or to.
* @param Value The value to serialize.
*/
template <typename StructType>
FORCEINLINE friend typename TEnableIf<TModels<CStaticStructProvider, StructType>::Value, FArchive&>::Type operator <<(FArchive& Ar, const StructType& Value)
{
StructType* MutableValue = const_cast<StructType*>(&Value);
StructType::StaticStruct()->SerializeItem(Ar, MutableValue, nullptr);
return Ar;
}
private:
uint32 CRC;
UObject* RootObject;
};
/**
* Serializes a USTRUCT value from or into an archive.
*
* @param Ar The archive to serialize from or to.
* @param Value The value to serialize.
*/
template <typename StructType>
FORCEINLINE typename TEnableIf<TModels<CStaticStructProvider, StructType>::Value, FArchive&>::Type operator <<(FArchive& Ar, const StructType& Value)
{
StructType* MutableValue = const_cast<StructType*>(&Value);
StructType::StaticStruct()->SerializeItem(Ar, MutableValue, nullptr);
return Ar;
}
@@ -137,10 +137,9 @@ public:
return (TClass*)Result;
}
friend FArchive& operator<<(FArchive& Ar, TSubclassOf& SubclassOf)
FORCEINLINE void SerializeTSubclassOf(FArchive& Ar)
{
Ar << SubclassOf.Class;
return Ar;
Ar << Class;
}
friend uint32 GetTypeHash(const TSubclassOf& SubclassOf)
@@ -166,3 +165,11 @@ struct TIsTSubclassOf<TSubclassOf<T>>
{
enum { Value = true };
};
template <typename T>
FArchive& operator<<(FArchive& Ar, TSubclassOf<T>& SubclassOf)
{
SubclassOf.SerializeTSubclassOf(Ar);
return Ar;
}
@@ -73,13 +73,13 @@ public:
return !(bool)*this;
}
inline friend bool operator==(const TAllFieldsIterator<T>& Lhs, const TAllFieldsIterator<T>& Rhs)
inline bool operator==(const TAllFieldsIterator<T>& Rhs) const
{
return *Lhs.FieldIterator == *Rhs.FieldIterator && Lhs.CurrentFieldIndex == Rhs.CurrentFieldIndex;
return *FieldIterator == *Rhs.FieldIterator && CurrentFieldIndex == Rhs.CurrentFieldIndex;
}
inline friend bool operator!=(const TAllFieldsIterator<T>& Lhs, const TAllFieldsIterator<T>& Rhs)
inline bool operator!=(const TAllFieldsIterator<T>& Rhs) const
{
return *Lhs.FieldIterator != *Rhs.FieldIterator || Lhs.CurrentFieldIndex != Rhs.CurrentFieldIndex;
return *FieldIterator != *Rhs.FieldIterator || CurrentFieldIndex != Rhs.CurrentFieldIndex;
}
inline void operator++()
@@ -437,19 +437,6 @@ public:
return FFieldPath::operator==(Other);
}
/**
* Compare weak pointers for inequality
* @param Other weak pointer to compare to
**/
template <typename OtherPropertyType>
FORCEINLINE bool operator!=(const TFieldPath<OtherPropertyType> &Other) const
{
static_assert(TPointerIsConvertibleFromTo<OtherPropertyType, const FField>::Value, "TFieldPath can only be compared with FField types");
static_assert(TPointerIsConvertibleFromTo<PropertyType, OtherPropertyType>::Value, "Unable to compare TFieldPath with raw pointer - types are incompatible");
return FFieldPath::operator!=(Other);
}
/**
* Compare weak pointers for equality
* @param Other pointer to compare to
@@ -463,6 +450,26 @@ public:
return Get() == Other;
}
FORCENOINLINE bool operator==(TYPE_OF_NULLPTR) const
{
return !Get();
}
#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
/**
* Compare weak pointers for inequality
* @param Other weak pointer to compare to
**/
template <typename OtherPropertyType>
FORCEINLINE bool operator!=(const TFieldPath<OtherPropertyType> &Other) const
{
static_assert(TPointerIsConvertibleFromTo<OtherPropertyType, const FField>::Value, "TFieldPath can only be compared with FField types");
static_assert(TPointerIsConvertibleFromTo<PropertyType, OtherPropertyType>::Value, "Unable to compare TFieldPath with raw pointer - types are incompatible");
return FFieldPath::operator!=(Other);
}
/**
* Compare weak pointers for inequality
* @param Other pointer to compare to
@@ -476,7 +483,6 @@ public:
return Get() != Other;
}
template <typename LhsT>
friend FORCENOINLINE bool operator==(const LhsT* Lhs, const TFieldPath<PropertyType>& Rhs)
{
@@ -488,11 +494,6 @@ public:
return Rhs == Lhs;
}
friend FORCENOINLINE bool operator==(const TFieldPath<PropertyType>& Lhs, TYPE_OF_NULLPTR)
{
return !Lhs.Get();
}
friend FORCENOINLINE bool operator==(TYPE_OF_NULLPTR, const TFieldPath<PropertyType>& Rhs)
{
return !Rhs.Get();
@@ -509,15 +510,16 @@ public:
return Rhs != Lhs;
}
friend FORCENOINLINE bool operator!=(const TFieldPath<PropertyType>& Lhs, TYPE_OF_NULLPTR)
FORCENOINLINE bool operator!=(TYPE_OF_NULLPTR) const
{
return !!Lhs.Get();
return !!Get();
}
friend FORCENOINLINE bool operator!=(TYPE_OF_NULLPTR, const TFieldPath<PropertyType>& Rhs)
{
return !!Rhs.Get();
}
#endif
};
// Helper function which deduces the type of the initializer
@@ -312,73 +312,95 @@ public:
}
/** Hash function. */
FORCEINLINE friend uint32 GetTypeHash(const TLazyObjectPtr<T>& LazyObjectPtr)
FORCEINLINE uint32 GetLazyObjecPtrTypeHash() const
{
return GetTypeHash(static_cast<const FLazyObjectPtr&>(LazyObjectPtr));
return GetTypeHash(static_cast<const FLazyObjectPtr&>(*this));
}
friend FArchive& operator<<(FArchive& Ar, TLazyObjectPtr<T>& LazyObjectPtr)
FORCEINLINE void SerializePtr(FArchive& Ar)
{
Ar << static_cast<FLazyObjectPtr&>(LazyObjectPtr);
return Ar;
Ar << static_cast<FLazyObjectPtr&>(*this);
}
/** Compare with another TLazyObjectPtr of related type */
template<typename U, typename = decltype((T*)nullptr == (U*)nullptr)>
friend FORCEINLINE bool operator==(const TLazyObjectPtr<T>& Lhs, const TLazyObjectPtr<U>& Rhs)
FORCEINLINE bool operator==(const TLazyObjectPtr<U>& Rhs) const
{
return (const FLazyObjectPtr&)Lhs == (const FLazyObjectPtr&)Rhs;
return (const FLazyObjectPtr&)*this == (const FLazyObjectPtr&)Rhs;
}
template<typename U, typename = decltype((T*)nullptr != (U*)nullptr)>
friend FORCEINLINE bool operator!=(const TLazyObjectPtr<T>& Lhs, const TLazyObjectPtr<U>& Rhs)
FORCEINLINE bool operator!=(const TLazyObjectPtr<U>& Rhs) const
{
return (const FLazyObjectPtr&)Lhs != (const FLazyObjectPtr&)Rhs;
return (const FLazyObjectPtr&)*this != (const FLazyObjectPtr&)Rhs;
}
/** Compare for equality with a raw pointer **/
template<typename U, typename = decltype((T*)nullptr == (U*)nullptr)>
friend FORCEINLINE bool operator==(const TLazyObjectPtr<T>& Lhs, const U* Rhs)
FORCEINLINE bool operator==(const U* Rhs) const
{
return Lhs.Get() == Rhs;
}
template<typename U, typename = decltype((T*)nullptr == (U*)nullptr)>
friend FORCEINLINE bool operator==(const U* Lhs, const TLazyObjectPtr<T>& Rhs)
{
return Lhs == Rhs.Get();
return Get() == Rhs;
}
/** Compare to null */
friend FORCEINLINE bool operator==(const TLazyObjectPtr<T>& Lhs, TYPE_OF_NULLPTR)
FORCEINLINE bool operator==(TYPE_OF_NULLPTR) const
{
return !Lhs.IsValid();
return !IsValid();
}
friend FORCEINLINE bool operator==(TYPE_OF_NULLPTR, const TLazyObjectPtr<T>& Rhs)
{
return !Rhs.IsValid();
}
/** Compare for inequality with a raw pointer **/
template<typename U, typename = decltype((T*)nullptr != (U*)nullptr)>
friend FORCEINLINE bool operator!=(const TLazyObjectPtr<T>& Lhs, const U* Rhs)
FORCEINLINE bool operator!=(const U* Rhs) const
{
return Lhs.Get() != Rhs;
}
template<typename U, typename = decltype((T*)nullptr != (U*)nullptr)>
friend FORCEINLINE bool operator!=(const U* Lhs, const TLazyObjectPtr<T>& Rhs)
{
return Lhs != Rhs.Get();
return Get() != Rhs;
}
/** Compare for inequality with null **/
friend FORCEINLINE bool operator!=(const TLazyObjectPtr<T>& Lhs, TYPE_OF_NULLPTR)
FORCEINLINE bool operator!=(TYPE_OF_NULLPTR) const
{
return Lhs.IsValid();
}
friend FORCEINLINE bool operator!=(TYPE_OF_NULLPTR, const TLazyObjectPtr<T>& Rhs)
{
return Rhs.IsValid();
return IsValid();
}
};
/** Hash function. */
template<typename T>
FORCEINLINE uint32 GetTypeHash(const TLazyObjectPtr<T>& LazyObjectPtr)
{
return LazyObjectPtr.GetLazyObjecPtrTypeHash();
}
template<typename T>
FArchive& operator<<(FArchive& Ar, TLazyObjectPtr<T>& LazyObjectPtr)
{
LazyObjectPtr.SerializePtr(Ar);
return Ar;
}
/** Compare for equality with a raw pointer **/
template<typename T, typename U, typename = decltype((T*)nullptr == (U*)nullptr)>
FORCEINLINE bool operator==(const U* Lhs, const TLazyObjectPtr<T>& Rhs)
{
return Lhs == Rhs.Get();
}
/** Compare to null */
template<typename T>
FORCEINLINE bool operator==(TYPE_OF_NULLPTR, const TLazyObjectPtr<T>& Rhs)
{
return !Rhs.IsValid();
}
/** Compare for inequality with a raw pointer **/
template<typename T, typename U, typename = decltype((T*)nullptr != (U*)nullptr)>
FORCEINLINE bool operator!=(const U* Lhs, const TLazyObjectPtr<T>& Rhs)
{
return Lhs != Rhs.Get();
}
/** Compare for inequality with null **/
template<typename T>
FORCEINLINE bool operator!=(TYPE_OF_NULLPTR, const TLazyObjectPtr<T>& Rhs)
{
return Rhs.IsValid();
}
template<class T> struct TIsPODType<TLazyObjectPtr<T> > { enum { Value = TIsPODType<FLazyObjectPtr>::Value }; };
template<class T> struct TIsWeakPointerType<TLazyObjectPtr<T> > { enum { Value = TIsWeakPointerType<FLazyObjectPtr>::Value }; };
@@ -120,8 +120,8 @@ struct FPackedObjectRef
// The least significant bit must always be 1 in a non-null reference.
UPTRINT EncodedRef;
friend inline bool operator==(FPackedObjectRef LHS, FPackedObjectRef RHS) { return LHS.EncodedRef == RHS.EncodedRef; }
friend inline bool operator!=(FPackedObjectRef LHS, FPackedObjectRef RHS) { return LHS.EncodedRef != RHS.EncodedRef; }
inline bool operator==(FPackedObjectRef RHS) const { return EncodedRef == RHS.EncodedRef; }
inline bool operator!=(FPackedObjectRef RHS) const { return EncodedRef != RHS.EncodedRef; }
friend inline uint32 GetTypeHash(FPackedObjectRef ObjectRef) { return GetTypeHash(ObjectRef.EncodedRef); }
};
@@ -326,6 +326,8 @@ namespace ObjectPtr_Private
template <typename T>
char (&ResolveTypeIsComplete(...))[1];
struct Friend;
};
/**
@@ -444,6 +446,24 @@ public:
{
return ObjectPtr == Other.ObjectPtr;
}
// Equality/Inequality comparisons against nullptr
FORCEINLINE bool operator==(TYPE_OF_NULLPTR) const
{
return !ObjectPtr.operator bool();
}
// Equality/Inequality comparisons against another type that can be implicitly converted to the pointer type kept in a TObjectPtr
template <
typename U,
typename = decltype(ObjectPtr_Private::IsObjectPtrEqual(std::declval<const TObjectPtr<T>&>(), std::declval<U&&>()))
>
FORCEINLINE bool operator==(U&& Other) const
{
return ObjectPtr_Private::IsObjectPtrEqual(*this, Other);
}
#if __cplusplus < 202002L
template <
typename U,
typename Base = std::decay_t<decltype(false ? std::declval<std::decay_t<T*>>() : std::declval<std::decay_t<U*>>())>
@@ -453,62 +473,20 @@ public:
return ObjectPtr != Other.ObjectPtr;
}
// Equality/Inequality comparisons against nullptr
FORCEINLINE bool operator==(TYPE_OF_NULLPTR) const
{
return !ObjectPtr.operator bool();
}
FORCEINLINE bool operator!=(TYPE_OF_NULLPTR) const
{
return ObjectPtr.operator bool();
}
friend FORCEINLINE bool operator==(TYPE_OF_NULLPTR, const TObjectPtr& Rhs)
{
return Rhs == nullptr;
}
friend FORCEINLINE bool operator!=(TYPE_OF_NULLPTR, const TObjectPtr& Rhs)
{
return Rhs != nullptr;
}
// Equality/Inequality comparisons against another type that can be implicitly converted to the pointer type kept in a TObjectPtr
template <
typename U,
typename = decltype(ObjectPtr_Private::IsObjectPtrEqual(std::declval<const TObjectPtr<T>&>(), std::declval<U&&>()))
>
friend FORCEINLINE bool operator==(const TObjectPtr<T>& Ptr, U&& Other)
FORCEINLINE bool operator!=(U&& Other) const
{
return ObjectPtr_Private::IsObjectPtrEqual(Ptr, Other);
}
template <
typename U,
typename = decltype(ObjectPtr_Private::IsObjectPtrEqual(std::declval<const TObjectPtr<T>&>(), std::declval<U&&>()))
>
friend FORCEINLINE bool operator==(U&& Other, const TObjectPtr<T>& Ptr)
{
return ObjectPtr_Private::IsObjectPtrEqual(Ptr, Other);
}
template <
typename U,
typename = decltype(ObjectPtr_Private::IsObjectPtrEqual(std::declval<const TObjectPtr<T>&>(), std::declval<U&&>()))
>
friend FORCEINLINE bool operator!=(const TObjectPtr<T>& Ptr, U&& Other)
{
return !ObjectPtr_Private::IsObjectPtrEqual(Ptr, Other);
}
template <
typename U,
typename = decltype(ObjectPtr_Private::IsObjectPtrEqual(std::declval<const TObjectPtr<T>&>(), std::declval<U&&>()))
>
friend FORCEINLINE bool operator!=(U&& Other, const TObjectPtr<T>& Ptr)
{
return !ObjectPtr_Private::IsObjectPtrEqual(Ptr, Other);
return !ObjectPtr_Private::IsObjectPtrEqual(*this, Other);
}
#endif
// @TODO: OBJPTR: There is a risk that the FObjectPtr is storing a reference to the wrong type. This could
// happen if data was serialized at a time when a pointer field was declared to be of type A, but then the declaration
@@ -548,22 +526,17 @@ public:
FORCEINLINE bool IsA(const UClass* SomeBase) const { return ObjectPtr.IsA(SomeBase); }
template <typename U> FORCEINLINE bool IsA() const { return ObjectPtr.IsA<U>(); }
friend FORCEINLINE uint32 GetTypeHash(const TObjectPtr<T>& InObjectPtr)
FORCEINLINE uint32 GetPtrTypeHash() const
{
return GetTypeHash(InObjectPtr.ObjectPtr);
return GetTypeHash(ObjectPtr);
}
friend FORCEINLINE FArchive& operator<<(FArchive& Ar, TObjectPtr<T>& InObjectPtr)
FORCEINLINE void SerializePtrStructured(FStructuredArchiveSlot Slot)
{
Ar << InObjectPtr.ObjectPtr;
return Ar;
}
friend FORCEINLINE void operator<<(FStructuredArchiveSlot Slot, TObjectPtr<T>& InObjectPtr)
{
Slot << InObjectPtr.ObjectPtr;
Slot << ObjectPtr;
}
friend ObjectPtr_Private::Friend;
friend struct FObjectPtr;
template <typename U> friend struct TObjectPtr;
template <typename U, typename V> friend bool ObjectPtr_Private::IsObjectPtrEqualToRawPtrOfRelatedType(const TObjectPtr<U>& Ptr, const V* Other);
@@ -615,8 +588,69 @@ namespace ObjectPtr_Private
template <typename T> struct TRawPointerType<const TObjectPtr<T>> { using Type = T*; };
template <typename T> struct TRawPointerType< volatile TObjectPtr<T>> { using Type = T*; };
template <typename T> struct TRawPointerType<const volatile TObjectPtr<T>> { using Type = T*; };
struct Friend
{
template <typename T>
FORCEINLINE static uint32 GetPtrTypeHash(const TObjectPtr<T>& InObjectPtr)
{
return GetTypeHash(InObjectPtr.ObjectPtr);
}
template <typename T>
FORCEINLINE static FArchive& Serialize(FArchive& Ar, TObjectPtr<T>& InObjectPtr)
{
Ar << InObjectPtr.ObjectPtr;
return Ar;
}
template <typename T>
FORCEINLINE static void SerializePtrStructured(FStructuredArchiveSlot Slot, TObjectPtr<T>& InObjectPtr)
{
Slot << InObjectPtr.ObjectPtr;
}
};
}
template <typename T>
FORCEINLINE uint32 GetTypeHash(const TObjectPtr<T>& InObjectPtr)
{
return ObjectPtr_Private::Friend::GetPtrTypeHash(InObjectPtr);
}
template <typename T>
FORCEINLINE FArchive& operator<<(FArchive& Ar, TObjectPtr<T>& InObjectPtr)
{
return ObjectPtr_Private::Friend::Serialize(Ar, InObjectPtr);
}
template <typename T>
FORCEINLINE void operator<<(FStructuredArchiveSlot Slot, TObjectPtr<T>& InObjectPtr)
{
ObjectPtr_Private::Friend::SerializePtrStructured(Slot, InObjectPtr);
}
#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
// Equality/Inequality comparisons against another type that can be implicitly converted to the pointer type kept in a TObjectPtr
template <
typename T,
typename U,
decltype(ObjectPtr_Private::IsObjectPtrEqual(std::declval<const TObjectPtr<T>&>(), std::declval<U&&>()))* = nullptr
>
FORCEINLINE bool operator==(U&& Other, const TObjectPtr<T>& Ptr)
{
return ObjectPtr_Private::IsObjectPtrEqual(Ptr, Other);
}
template <
typename T,
typename U,
decltype(ObjectPtr_Private::IsObjectPtrEqual(std::declval<const TObjectPtr<T>&>(), std::declval<U&&>()))* = nullptr
>
FORCEINLINE bool operator!=(U&& Other, const TObjectPtr<T>& Ptr)
{
return !ObjectPtr_Private::IsObjectPtrEqual(Ptr, Other);
}
#endif
template <typename T>
TPrivateObjectPtr<T> MakeObjectPtrUnsafe(const UObject* Obj);
@@ -223,9 +223,9 @@ public:
*
* @param Other soft pointer to compare to
*/
FORCEINLINE friend bool operator==(const TSoftObjectPtr& Lhs, const TSoftObjectPtr& Rhs)
FORCEINLINE bool operator==(const TSoftObjectPtr& Rhs) const
{
return Lhs.SoftObjectPtr == Rhs.SoftObjectPtr;
return SoftObjectPtr == Rhs.SoftObjectPtr;
}
/**
@@ -234,20 +234,21 @@ public:
*
* @param Other soft pointer to compare to
*/
FORCEINLINE friend bool operator==(const TSoftObjectPtr& Lhs, TYPE_OF_NULLPTR)
FORCEINLINE bool operator==(TYPE_OF_NULLPTR) const
{
return Lhs.SoftObjectPtr == nullptr;
return SoftObjectPtr == nullptr;
}
#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
/**
* Compare soft pointers for equality
* Compare soft pointers for inequality
* Caution: Two soft pointers might not be equal to each other, but they both might return nullptr
*
* @param Other soft pointer to compare to
*/
FORCEINLINE friend bool operator==(TYPE_OF_NULLPTR, const TSoftObjectPtr& Rhs)
FORCEINLINE bool operator!=(const TSoftObjectPtr& Rhs) const
{
return nullptr == Rhs.SoftObjectPtr;
return SoftObjectPtr != Rhs.SoftObjectPtr;
}
/**
@@ -256,32 +257,11 @@ public:
*
* @param Other soft pointer to compare to
*/
FORCEINLINE friend bool operator!=(const TSoftObjectPtr& Lhs, const TSoftObjectPtr& Rhs)
FORCEINLINE bool operator!=(TYPE_OF_NULLPTR) const
{
return Lhs.SoftObjectPtr != Rhs.SoftObjectPtr;
}
/**
* Compare soft pointers for inequality
* Caution: Two soft pointers might not be equal to each other, but they both might return nullptr
*
* @param Other soft pointer to compare to
*/
FORCEINLINE friend bool operator!=(const TSoftObjectPtr& Lhs, TYPE_OF_NULLPTR)
{
return Lhs.SoftObjectPtr != nullptr;
}
/**
* Compare soft pointers for inequality
* Caution: Two soft pointers might not be equal to each other, but they both might return nullptr
*
* @param Other soft pointer to compare to
*/
FORCEINLINE friend bool operator!=(TYPE_OF_NULLPTR, const TSoftObjectPtr& Rhs)
{
return nullptr != Rhs.SoftObjectPtr;
return SoftObjectPtr != nullptr;
}
#endif
/**
* Dereference the soft pointer.
@@ -377,21 +357,61 @@ public:
}
/** Hash function */
FORCEINLINE friend uint32 GetTypeHash(const TSoftObjectPtr<T>& Other)
FORCEINLINE uint32 GetPtrTypeHash() const
{
return GetTypeHash(static_cast<const TPersistentObjectPtr<FSoftObjectPath>&>(Other.SoftObjectPtr));
return GetTypeHash(static_cast<const TPersistentObjectPtr<FSoftObjectPath>&>(SoftObjectPtr));
}
friend FArchive& operator<<(FArchive& Ar, TSoftObjectPtr<T>& Other)
FORCEINLINE void Serialize(FArchive& Ar)
{
Ar << Other.SoftObjectPtr;
return Ar;
Ar << SoftObjectPtr;
}
private:
FSoftObjectPtr SoftObjectPtr;
};
#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
template<class T>
FORCEINLINE bool operator==(TYPE_OF_NULLPTR, const TSoftObjectPtr<T>& Rhs)
{
return Rhs == nullptr;
}
template<class T>
FORCEINLINE bool operator!=(TYPE_OF_NULLPTR, const TSoftObjectPtr<T>& Rhs)
{
return Rhs != nullptr;
}
template<class T>
FORCEINLINE bool operator==(const T* Lhs, const TSoftObjectPtr<T>& Rhs)
{
return Rhs == Lhs;
}
template<class T>
FORCEINLINE bool operator!=(const T* Lhs, const TSoftObjectPtr<T>& Rhs)
{
return Rhs != Lhs;
}
#endif
/** Hash function */
template<class T>
FORCEINLINE uint32 GetTypeHash(const TSoftObjectPtr<T>& Ptr)
{
return Ptr.GetPtrTypeHash();
}
template<class T>
FArchive& operator<<(FArchive& Ar, TSoftObjectPtr<T>& Ptr)
{
Ptr.Serialize(Ar);
return Ar;
}
template<class T> struct TIsPODType<TSoftObjectPtr<T> > { enum { Value = TIsPODType<FSoftObjectPtr>::Value }; };
template<class T> struct TIsWeakPointerType<TSoftObjectPtr<T> > { enum { Value = TIsWeakPointerType<FSoftObjectPtr>::Value }; };
@@ -475,21 +495,22 @@ public:
*
* @param Other soft pointer to compare to
*/
FORCEINLINE friend bool operator==(const TSoftClassPtr& Lhs, const TSoftClassPtr& Rhs)
FORCEINLINE bool operator==(const TSoftClassPtr& Rhs) const
{
return Lhs.SoftObjectPtr == Rhs.SoftObjectPtr;
return SoftObjectPtr == Rhs.SoftObjectPtr;
}
#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
/**
* Compare soft pointers for inequality
* Caution: Two soft pointers might not be equal to each other, but they both might return nullptr
*
* @param Other soft pointer to compare to
*/
FORCEINLINE friend bool operator!=(const TSoftClassPtr& Lhs, const TSoftClassPtr& Rhs)
FORCEINLINE bool operator!=(const TSoftClassPtr& Rhs) const
{
return Lhs.SoftObjectPtr != Rhs.SoftObjectPtr;
return SoftObjectPtr != Rhs.SoftObjectPtr;
}
#endif
/**
* Dereference the soft pointer
@@ -586,9 +607,9 @@ public:
}
/** Hash function */
FORCEINLINE friend uint32 GetTypeHash(const TSoftClassPtr<TClass>& Other)
FORCEINLINE uint32 GetPtrTypeHash() const
{
return GetTypeHash(static_cast<const TPersistentObjectPtr<FSoftObjectPath>&>(Other.SoftObjectPtr));
return GetTypeHash(static_cast<const TPersistentObjectPtr<FSoftObjectPath>&>(SoftObjectPtr));
}
/** Synchronously load (if necessary) and return the asset object represented by this asset ptr */
@@ -603,10 +624,9 @@ public:
return Class;
}
friend FArchive& operator<<(FArchive& Ar, TSoftClassPtr<TClass>& Other)
inline void Serialize(FArchive& Ar)
{
Ar << static_cast<FSoftObjectPtr&>(Other.SoftObjectPtr);
return Ar;
Ar << static_cast<FSoftObjectPtr&>(SoftObjectPtr);
}
private:
@@ -648,3 +668,31 @@ T* TSoftObjectPtr<T>::Get() const
{
return dynamic_cast<T*>(SoftObjectPtr.Get());
}
#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
template<class TClass>
FORCEINLINE bool operator==(const UClass* Lhs, const TSoftClassPtr<TClass>& Rhs)
{
return Rhs == Lhs;
}
template<class TClass>
FORCEINLINE bool operator!=(const UClass* Lhs, const TSoftClassPtr<TClass>& Rhs)
{
return Rhs != Lhs;
}
#endif
/** Hash function */
template<class TClass>
FORCEINLINE uint32 GetTypeHash(const TSoftClassPtr<TClass>& Ptr)
{
return Ptr.GetPtrTypeHash();
}
template<class TClass>
FArchive& operator<<(FArchive& Ar, TSoftClassPtr<TClass>& Ptr)
{
Ptr.Serialize(Ar);
return Ar;
}
@@ -309,7 +309,7 @@ public:
return const_cast<TStructOnScope*>(this)->CastChecked<U>();
}
friend FArchive& operator<<(FArchive& Ar, TStructOnScope& InStruct)
void Serialize(FArchive& Ar)
{
if (Ar.IsLoading())
{
@@ -321,30 +321,28 @@ public:
if (ScriptStructPtr == nullptr || !ScriptStructPtr->IsChildOf(TBaseStructure<T>::Get()))
{
Ar.SetError();
return Ar;
return;
}
InStruct.ScriptStruct = ScriptStructPtr;
InStruct.Initialize();
ScriptStructPtr->SerializeItem(Ar, InStruct.SampleStructMemory, nullptr);
ScriptStruct = ScriptStructPtr;
Initialize();
ScriptStructPtr->SerializeItem(Ar, SampleStructMemory, nullptr);
}
}
// Saving
else
{
FString StructPath;
if (UScriptStruct* ScriptStructPtr = const_cast<UScriptStruct*>(::Cast<UScriptStruct>(InStruct.ScriptStruct.Get())))
if (UScriptStruct* ScriptStructPtr = const_cast<UScriptStruct*>(::Cast<UScriptStruct>(ScriptStruct.Get())))
{
StructPath = ScriptStructPtr->GetPathName();
Ar << StructPath;
ScriptStructPtr->SerializeItem(Ar, InStruct.SampleStructMemory, nullptr);
ScriptStructPtr->SerializeItem(Ar, SampleStructMemory, nullptr);
}
else
{
Ar << StructPath;
}
}
return Ar;
}
private:
@@ -370,3 +368,10 @@ FORCEINLINE TStructOnScope<T> MakeStructOnScope(TArgs&&... Args)
Struct.template InitializeAs<U>(Forward<TArgs>(Args)...);
return Struct;
}
template<typename T>
FArchive& operator<<(FArchive& Ar, TStructOnScope<T>& Struct)
{
Struct.Serialize(Ar);
return Ar;
}
@@ -1006,8 +1006,8 @@ public:
Advance();
}
friend bool operator==(const TIterator& Lhs, const TIterator& Rhs) { return Lhs.Index == Rhs.Index; }
friend bool operator!=(const TIterator& Lhs, const TIterator& Rhs) { return Lhs.Index != Rhs.Index; }
bool operator==(const TIterator& Rhs) const { return Index == Rhs.Index; }
bool operator!=(const TIterator& Rhs) const { return Index != Rhs.Index; }
/** Conversion to "bool" returning true if the iterator is valid. */
FORCEINLINE explicit operator bool() const
@@ -315,8 +315,8 @@ public:
return (T*)GetObject();
}
FORCEINLINE friend bool operator==(const TObjectIterator& Lhs, const TObjectIterator& Rhs) { return Lhs.Index == Rhs.Index; }
FORCEINLINE friend bool operator!=(const TObjectIterator& Lhs, const TObjectIterator& Rhs) { return Lhs.Index != Rhs.Index; }
FORCEINLINE bool operator==(const TObjectIterator& Rhs) const { return Index == Rhs.Index; }
FORCEINLINE bool operator!=(const TObjectIterator& Rhs) const { return Index != Rhs.Index; }
protected:
/**
@@ -6638,8 +6638,8 @@ public:
return !(bool)*this;
}
inline friend bool operator==(const TFieldIterator<T>& Lhs, const TFieldIterator<T>& Rhs) { return Lhs.Field == Rhs.Field; }
inline friend bool operator!=(const TFieldIterator<T>& Lhs, const TFieldIterator<T>& Rhs) { return Lhs.Field != Rhs.Field; }
inline bool operator==(const TFieldIterator<T>& Rhs) const { return Field == Rhs.Field; }
inline bool operator!=(const TFieldIterator<T>& Rhs) const { return Field != Rhs.Field; }
inline void operator++()
{
@@ -6979,14 +6979,14 @@ public:
return false;
}
FORCEINLINE friend bool operator==(const FPropertyValueIterator& Lhs, const FPropertyValueIterator& Rhs)
FORCEINLINE bool operator==(const FPropertyValueIterator& Rhs) const
{
return Lhs.PropertyIteratorStack == Rhs.PropertyIteratorStack;
return PropertyIteratorStack == Rhs.PropertyIteratorStack;
}
FORCEINLINE friend bool operator!=(const FPropertyValueIterator& Lhs, const FPropertyValueIterator& Rhs)
FORCEINLINE bool operator!=(const FPropertyValueIterator& Rhs) const
{
return !(Lhs.PropertyIteratorStack == Rhs.PropertyIteratorStack);
return !(PropertyIteratorStack == Rhs.PropertyIteratorStack);
}
/** Returns a TPair containing Property/Value currently being iterated */
@@ -7086,9 +7086,9 @@ private:
: Owner(InValue)
{}
FORCEINLINE friend bool operator==(const FPropertyValueStackEntry& Lhs, const FPropertyValueStackEntry& Rhs)
FORCEINLINE bool operator==(const FPropertyValueStackEntry& Rhs) const
{
return Lhs.Owner == Rhs.Owner && Lhs.ValueIndex == Rhs.ValueIndex;
return Owner == Rhs.Owner && ValueIndex == Rhs.ValueIndex;
}
FORCEINLINE const BasePairType& GetPropertyValue() const
@@ -212,11 +212,10 @@ public:
return GetTypeHash(WeakObjectPtr.Field);
}
friend FArchive& operator<<(FArchive& Ar, TWeakFieldPtr& InWeakFieldPtr)
FORCEINLINE void Serialize(FArchive& Ar)
{
Ar << InWeakFieldPtr.Owner;
Ar << InWeakFieldPtr.Field;
return Ar;
Ar << Owner;
Ar << Field;
}
/**
@@ -347,4 +346,11 @@ struct TWeakFieldPtrMapKeyFuncs : public TDefaultMapKeyFuncs<KeyType, ValueType,
{
return GetTypeHash(Key);
}
};
};
template<class T>
FArchive& operator<<(FArchive& Ar, TWeakFieldPtr<T>& WeakFieldPtr)
{
WeakFieldPtr.Serialize(Ar);
return Ar;
}
@@ -129,6 +129,7 @@ public:
(!IsValid() && !Other.IsValid());
}
#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
/**
* Compare weak pointers for inequality
* @param Other weak pointer to compare to
@@ -139,6 +140,7 @@ public:
(ObjectIndex != Other.ObjectIndex || ObjectSerialNumber != Other.ObjectSerialNumber) &&
(IsValid() || Other.IsValid());
}
#endif
/**
* Returns true if two weak pointers were originally set to the same object, even if they are now stale
@@ -215,9 +217,9 @@ public:
}
/** Hash function. */
friend uint32 GetTypeHash(const FWeakObjectPtr& WeakObjectPtr)
FORCEINLINE uint32 GetTypeHash() const
{
return uint32(WeakObjectPtr.ObjectIndex ^ WeakObjectPtr.ObjectSerialNumber);
return uint32(ObjectIndex ^ ObjectSerialNumber);
}
/**
@@ -332,3 +334,10 @@ template<> struct TIsWeakPointerType<FWeakObjectPtr> { enum { Value = true }; };
// Typedef script delegates for convenience.
typedef TScriptDelegate<> FScriptDelegate;
typedef TMulticastScriptDelegate<> FMulticastScriptDelegate;
/** Hash function. */
FORCEINLINE uint32 GetTypeHash(const FWeakObjectPtr& WeakObjectPtr)
{
return WeakObjectPtr.GetTypeHash();
}