-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathUnrealTemplate.h
106 lines (87 loc) · 2.81 KB
/
UnrealTemplate.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#pragma once
#include "inc.h"
#include "EnableIf.h"
#include "RemoveReference.h"
#include "AndOrNot.h"
#include "IsArithmetic.h"
#include "IsPointer.h"
#include "TypeCompatibleBytes.h"
template <typename T> struct TRValueToLValueReference { typedef T Type; };
template <typename T> struct TRValueToLValueReference<T&&> { typedef T& Type; };
template<typename ReferencedType>
FORCEINLINE ReferencedType* IfAThenAElseB(ReferencedType* A, ReferencedType* B)
{
using PTRINT = int64;
const PTRINT IntA = reinterpret_cast<PTRINT>(A);
const PTRINT IntB = reinterpret_cast<PTRINT>(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<ReferencedType*>(IntA | (MaskB & IntB));
}
template<typename T>//, typename = typename TEnableIf<TIsContiguousContainer<T>::Value>::Type>
auto GetData(T&& Container) -> decltype(Container.GetData())
{
return Container.GetData();
}
template <typename T, SIZE_T N>
constexpr T* GetData(T(&Container)[N])
{
return Container;
}
template <typename T>
constexpr T* GetData(std::initializer_list<T> List)
{
return List.begin();
}
template<typename T>//, typename = typename TEnableIf<TIsContiguousContainer<T>::Value>::Type>
SIZE_T GetNum(T&& Container)
{
return (SIZE_T)Container.Num();
}
template <typename T>
FORCEINLINE T&& Forward(typename TRemoveReference<T>::Type& Obj)
{
return (T&&)Obj;
}
template <typename T>
FORCEINLINE T&& Forward(typename TRemoveReference<T>::Type&& Obj)
{
return (T&&)Obj;
}
template <typename T>
FORCEINLINE typename TRemoveReference<T>::Type&& MoveTemp(T&& Obj)
{
typedef typename TRemoveReference<T>::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<T>::Value, "MoveTemp called on an rvalue");
// static_assert(!TAreTypesEqual<CastType&, const CastType&>::Value, "MoveTemp called on a const object");
return (CastType&&)Obj;
}
template <typename T>
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<T>, TIsArithmetic<T>>::Value };
};
template <typename T>
inline typename TEnableIf<!TUseBitwiseSwap<T>::Value>::Type Swap(T& A, T& B)
{
T Temp = MoveTemp(A);
A = MoveTemp(B);
B = MoveTemp(Temp);
}
#define LIKELY(x) (x)
template <typename T>
inline typename TEnableIf<TUseBitwiseSwap<T>::Value>::Type Swap(T& A, T& B)
{
if (LIKELY(&A != &B))
{
TTypeCompatibleBytes<T> 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));
}
}