#pragma once #include "inc.h" #include "EnableIf.h" #include "RemoveReference.h" #include "AndOrNot.h" #include "IsArithmetic.h" #include "IsPointer.h" #include "TypeCompatibleBytes.h" template struct TRValueToLValueReference { typedef T Type; }; template struct TRValueToLValueReference { typedef T& Type; }; template FORCEINLINE ReferencedType* IfAThenAElseB(ReferencedType* A, ReferencedType* B) { using PTRINT = int64; const PTRINT IntA = reinterpret_cast(A); const PTRINT IntB = reinterpret_cast(B); // Compute a mask which has all bits set if IntA is zero, and no bits set if it's non-zero. const PTRINT MaskB = -(!IntA); return reinterpret_cast(IntA | (MaskB & IntB)); } template//, typename = typename TEnableIf::Value>::Type> auto GetData(T&& Container) -> decltype(Container.GetData()) { return Container.GetData(); } template constexpr T* GetData(T(&Container)[N]) { return Container; } template constexpr T* GetData(std::initializer_list List) { return List.begin(); } template//, typename = typename TEnableIf::Value>::Type> SIZE_T GetNum(T&& Container) { return (SIZE_T)Container.Num(); } template FORCEINLINE T&& Forward(typename TRemoveReference::Type& Obj) { return (T&&)Obj; } template FORCEINLINE T&& Forward(typename TRemoveReference::Type&& Obj) { return (T&&)Obj; } template FORCEINLINE typename TRemoveReference::Type&& MoveTemp(T&& Obj) { typedef typename TRemoveReference::Type CastType; // Validate that we're not being passed an rvalue or a const object - the former is redundant, the latter is almost certainly a mistake // static_assert(TIsLValueReferenceType::Value, "MoveTemp called on an rvalue"); // static_assert(!TAreTypesEqual::Value, "MoveTemp called on a const object"); return (CastType&&)Obj; } template struct TUseBitwiseSwap { // We don't use bitwise swapping for 'register' types because this will force them into memory and be slower. enum { Value = !TOrValue<__is_enum(T), TIsPointer, TIsArithmetic>::Value }; }; template inline typename TEnableIf::Value>::Type Swap(T& A, T& B) { T Temp = MoveTemp(A); A = MoveTemp(B); B = MoveTemp(Temp); } #define LIKELY(x) (x) template inline typename TEnableIf::Value>::Type Swap(T& A, T& B) { if (LIKELY(&A != &B)) { TTypeCompatibleBytes Temp; // FMemory::Memcpy(&Temp, &A, sizeof(T)); // FMemory::Memcpy(&A, &B, sizeof(T)); // FMemory::Memcpy(&B, &Temp, sizeof(T)); memcpy(&Temp, &A, sizeof(T)); memcpy(&A, &B, sizeof(T)); memcpy(&B, &Temp, sizeof(T)); } }