From 172a92edfedf65620f4823c2b91f6f1deafa9329 Mon Sep 17 00:00:00 2001
From: _Redstone_c_ <myredstone1024@gmail.com>
Date: Thu, 3 Feb 2022 16:45:34 +0800
Subject: [PATCH] feat(templates): add basic tools such as
 Templates/Templates.h

---
 .../Source/Public/Templates/Container.h       | 45 ++++++++++
 .../Source/Public/Templates/Noncopyable.h     | 25 ++++++
 .../Source/Public/Templates/Templates.h       |  6 ++
 .../Source/Public/Templates/Utility.h         | 85 +++++++++++++++++++
 4 files changed, 161 insertions(+)
 create mode 100644 Redcraft.Utility/Source/Public/Templates/Container.h
 create mode 100644 Redcraft.Utility/Source/Public/Templates/Noncopyable.h
 create mode 100644 Redcraft.Utility/Source/Public/Templates/Templates.h
 create mode 100644 Redcraft.Utility/Source/Public/Templates/Utility.h

diff --git a/Redcraft.Utility/Source/Public/Templates/Container.h b/Redcraft.Utility/Source/Public/Templates/Container.h
new file mode 100644
index 0000000..99dd079
--- /dev/null
+++ b/Redcraft.Utility/Source/Public/Templates/Container.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "CoreTypes.h"
+
+NAMESPACE_REDCRAFT_BEGIN
+NAMESPACE_MODULE_BEGIN(Redcraft)
+NAMESPACE_MODULE_BEGIN(Utility)
+
+template <typename T> requires requires(T Container) { Container.GetData(); }
+constexpr auto GetData(T&& Container)
+{
+	return Container.GetData();
+}
+
+template <typename T, size_t N> constexpr       T* GetData(T(&Container)[N]) { return Container; }
+template <typename T, size_t N> constexpr       T* GetData(T(&& Container)[N]) { return Container; }
+template <typename T, size_t N> constexpr const T* GetData(const T(&Container)[N]) { return Container; }
+template <typename T, size_t N> constexpr const T* GetData(const T(&& Container)[N]) { return Container; }
+
+template <typename T> requires requires(T Container) { Container.data(); }
+constexpr auto GetData(T&& Container)
+{
+	return Container.data();
+}
+
+template <typename T> requires requires(T Container) { Container.Num(); }
+constexpr auto GetNum(T&& Container)
+{
+	return Container.Num();
+}
+
+template <typename T, size_t N> constexpr size_t GetNum(T(&Container)[N]) { return N; }
+template <typename T, size_t N> constexpr size_t GetNum(T(&& Container)[N]) { return N; }
+template <typename T, size_t N> constexpr size_t GetNum(const T(&Container)[N]) { return N; }
+template <typename T, size_t N> constexpr size_t GetNum(const T(&& Container)[N]) { return N; }
+
+template <typename T> requires requires(T Container) { Container.size(); }
+constexpr auto GetNum(T&& Container)
+{
+	return Container.size();
+}
+
+NAMESPACE_MODULE_END(Utility)
+NAMESPACE_MODULE_END(Redcraft)
+NAMESPACE_REDCRAFT_END
diff --git a/Redcraft.Utility/Source/Public/Templates/Noncopyable.h b/Redcraft.Utility/Source/Public/Templates/Noncopyable.h
new file mode 100644
index 0000000..d970585
--- /dev/null
+++ b/Redcraft.Utility/Source/Public/Templates/Noncopyable.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "CoreTypes.h"
+
+NAMESPACE_REDCRAFT_BEGIN
+NAMESPACE_MODULE_BEGIN(Redcraft)
+NAMESPACE_MODULE_BEGIN(Utility)
+
+struct FNoncopyable
+{
+	FNoncopyable(const FNoncopyable&) = delete;
+	FNoncopyable& operator=(const FNoncopyable&) = delete;
+};
+
+struct FNonmovable
+{
+	FNonmovable(const FNonmovable&&) = delete;
+	FNonmovable& operator=(const FNonmovable&&) = delete;
+};
+
+struct FSingleton : public FNoncopyable, public FNonmovable { };
+
+NAMESPACE_MODULE_END(Utility)
+NAMESPACE_MODULE_END(Redcraft)
+NAMESPACE_REDCRAFT_END
diff --git a/Redcraft.Utility/Source/Public/Templates/Templates.h b/Redcraft.Utility/Source/Public/Templates/Templates.h
new file mode 100644
index 0000000..f1e8c87
--- /dev/null
+++ b/Redcraft.Utility/Source/Public/Templates/Templates.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "CoreTypes.h"
+#include "Templates/Utility.h"
+#include "Templates/Container.h"
+#include "Templates/Noncopyable.h"
diff --git a/Redcraft.Utility/Source/Public/Templates/Utility.h b/Redcraft.Utility/Source/Public/Templates/Utility.h
new file mode 100644
index 0000000..d3f79a1
--- /dev/null
+++ b/Redcraft.Utility/Source/Public/Templates/Utility.h
@@ -0,0 +1,85 @@
+#pragma once
+
+#include "CoreTypes.h"
+#include "TypeTraits/TypeTraits.h"
+
+NAMESPACE_REDCRAFT_BEGIN
+NAMESPACE_MODULE_BEGIN(Redcraft)
+NAMESPACE_MODULE_BEGIN(Utility)
+
+template <typename T>
+constexpr const T& AsConst(T& Ref)
+{
+	return Ref;
+}
+
+template <typename T>
+void AsConst(const T&& Ref) = delete;
+
+template <typename T, size_t N>
+constexpr const T(&AsConst(T(&Array)[N]))[N]
+{
+	return Array;
+}
+
+template <typename T>
+FORCEINLINE typename TRemoveReference<T>::Type&& MoveTemp(T&& Obj)
+{
+	typedef typename TRemoveReference<T>::Type CastType;
+	
+	static_assert(TIsLValueReference<T>::Value, "MoveTemp called on an rvalue.");
+	static_assert(!TIsConst<CastType>::Value, "MoveTemp called on a const object.");
+
+	return (CastType&&)Obj;
+}
+
+template <typename T>
+FORCEINLINE T CopyTemp(T& Val)
+{
+	return const_cast<const T&>(Val);
+}
+
+template <typename T>
+FORCEINLINE T CopyTemp(const T& Val)
+{
+	return Val;
+}
+
+template <typename T>
+FORCEINLINE T&& CopyTemp(T&& Val)
+{
+	return MoveTemp(Val);
+}
+
+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 void Swap(T& A, T& B)
+{
+	T Temp = MoveTemp(A);
+	A = MoveTemp(B);
+	B = MoveTemp(Temp);
+}
+
+template <typename T>
+FORCEINLINE void Exchange(T& A, T& B)
+{
+	Swap(A, B);
+}
+
+template <typename T>
+T&& DeclVal();
+
+NAMESPACE_MODULE_END(Utility)
+NAMESPACE_MODULE_END(Redcraft)
+NAMESPACE_REDCRAFT_END