From 256e789c9b3fa1a7d3b788b848b6357205034ddd Mon Sep 17 00:00:00 2001 From: ninemine <1371605831@qq.com> Date: Thu, 18 Sep 2025 15:38:52 +0800 Subject: [PATCH] Update CP --- CP.hpp | 4 - detail/CP/Arithmetic.hpp | 343 +++++++++++++++++++- detail/CP/CBool.hpp | 8 +- detail/CP/CHash.hpp | 53 ++-- detail/CP/Typen.hpp | 663 +++++++++++++++++++++++++++++++++++---- 5 files changed, 991 insertions(+), 80 deletions(-) diff --git a/CP.hpp b/CP.hpp index b9aa4ed..324f982 100644 --- a/CP.hpp +++ b/CP.hpp @@ -6,12 +6,8 @@ #ifndef __FILE_Operator_Hpp #define __FILE_Operator_Hpp -#include "detail/CP/CHash.hpp" #include "detail/CP/CBool.hpp" -#include "detail/CP/CWhile.hpp" -#include "detail/CP/MaxMin.hpp" #include "detail/CP/Arithmetic.hpp" #include "detail/CP/Typen.hpp" -#include "detail\CP\CPString.hpp" #endif // __FILE_Operator_Hpp diff --git a/detail/CP/Arithmetic.hpp b/detail/CP/Arithmetic.hpp index 4d65bc2..b5d8895 100644 --- a/detail/CP/Arithmetic.hpp +++ b/detail/CP/Arithmetic.hpp @@ -2,7 +2,9 @@ #ifndef __FILE_Detail_CP_Arithmetic_Hpp #define __FILE_Detail_CP_Arithmetic_Hpp -#include "detail/CP/CHash.hpp" +#include "CHash.hpp" + +#pragma region TIsArithmetic namespace Internal { @@ -37,6 +39,10 @@ namespace Internal template constexpr bool TIsArithmetic = Internal::TIsArithmeticTool::Value; +#pragma endregion + +#pragma region TIsSigned + namespace Internal { /** @@ -60,4 +66,339 @@ namespace Internal template constexpr bool TIsSigned = Internal::TIsSignedTool::Value; +#pragma endregion + +#pragma region TIsIntegral + +namespace Internal +{ + /** + * Traits class which tests if a type is integral. + */ + template + struct TIsIntegralTool + { + constexpr static bool Value = false; + }; + + template <> struct TIsIntegralTool< bool> { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool< char> { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool< char16_t> { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool< char32_t> { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool< wchar_t> { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool< short> { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool< int> { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool< long> { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool< long long> { constexpr static bool Value = true; }; + template <> struct TIsIntegralTool { constexpr static bool Value = true; }; + + template struct TIsIntegralTool { constexpr static bool Value = TIsIntegralTool::Value; }; + template struct TIsIntegralTool< volatile T> { constexpr static bool Value = TIsIntegralTool::Value; }; + template struct TIsIntegralTool { constexpr static bool Value = TIsIntegralTool::Value; }; +} + +template constexpr bool TIsIntegral = Internal::TIsIntegralTool::Value; + +#pragma endregion + +#pragma region TIsFloatingPoint + +/////////////////////////////// +// TIsFloatingPoint + +namespace Internal +{ + /** + * Traits class which tests if a type is floating point. + */ + template + struct TIsFloatingPointTool + { + constexpr static bool Value = false; + }; + + template <> struct TIsFloatingPointTool { constexpr static bool Value = true; }; + template <> struct TIsFloatingPointTool { constexpr static bool Value = true; }; + template <> struct TIsFloatingPointTool { constexpr static bool Value = true; }; + + template struct TIsFloatingPointTool { constexpr static bool Value = TIsFloatingPointTool::Value; }; + template struct TIsFloatingPointTool< volatile T> { constexpr static bool Value = TIsFloatingPointTool::Value; }; + template struct TIsFloatingPointTool { constexpr static bool Value = TIsFloatingPointTool::Value; }; +} + +template constexpr bool TIsFloatingPoint = Internal::TIsFloatingPointTool::Value; + +// TIsFloatingPoint +////////////////////////////////// + +#pragma endregion + +#pragma region About Align + +/////////////////////// +// About Align Toolkit + +#pragma region Align + +/** + * Aligns a value to the nearest higher multiple of 'Alignment', which must be a power of two. + * + * @param Val The value to align. + * @param Alignment The alignment value, must be a power of two. + * + * @return The value aligned up to the specified alignment. + */ +template +FORCEINLINE constexpr T CAlign(T Val, uint64_t Alignment) +{ + return (T)(((uint64_t)Val + Alignment - 1) & ~(Alignment - 1)); +} + +/** + * Aligns a value to the nearest higher multiple of 'Alignment', which must be a power of two. + * + * @param Val The value to align. + * @param Alignment The alignment value, must be a power of two. + * + * @return The value aligned up to the specified alignment. + */ +template +FORCEINLINE T Align(T Val, uint64_t Alignment) +{ + return (T)(((uint64_t)Val + Alignment - 1) & ~(Alignment - 1)); +} + +#pragma endregion + +#pragma region AlignDown + +/** + * Aligns a value to the nearest lower multiple of 'Alignment', which must be a power of two. + * + * @param Val The value to align. + * @param Alignment The alignment value, must be a power of two. + * + * @return The value aligned down to the specified alignment. + */ +template +FORCEINLINE constexpr T CAlignDown(T Val, uint64_t Alignment) +{ + return (T)(((uint64_t)Val) & ~(Alignment - 1)); +} + +/** + * Aligns a value to the nearest lower multiple of 'Alignment', which must be a power of two. + * + * @param Val The value to align. + * @param Alignment The alignment value, must be a power of two. + * + * @return The value aligned down to the specified alignment. + */ +template +FORCEINLINE T AlignDown(T Val, uint64_t Alignment) +{ + return (T)(((uint64_t)Val) & ~(Alignment - 1)); +} + +#pragma endregion + +#pragma region IsAligned + +/** + * Checks if a pointer is aligned to the specified alignment. + * + * @param Val The value to align. + * @param Alignment The alignment value, must be a power of two. + * + * @return true if the pointer is aligned to the specified alignment, false otherwise. + */ +template +FORCEINLINE constexpr bool CIsAligned(T Val, uint64_t Alignment) +{ + return !((uint64_t)Val & (Alignment - 1)); +} + +/** + * Checks if a pointer is aligned to the specified alignment. + * + * @param Val The value to align. + * @param Alignment The alignment value, must be a power of two. + * + * @return true if the pointer is aligned to the specified alignment, false otherwise. + */ +template +FORCEINLINE bool IsAligned(T Val, uint64_t Alignment) +{ + return !((uint64_t)Val & (Alignment - 1)); +} + +#pragma endregion + +#pragma region AlignArbitrary + +/** + * Aligns a value to the nearest higher multiple of 'Alignment'. + * + * @param Val The value to align. + * @param Alignment The alignment value, can be any arbitrary value. + * + * @return The value aligned up to the specified alignment. + */ +template +FORCEINLINE constexpr T CAlignArbitrary(T Val, uint64_t Alignment) +{ + return (T)((((uint64_t)Val + Alignment - 1) / Alignment) * Alignment); +} + +/** + * Aligns a value to the nearest higher multiple of 'Alignment'. + * + * @param Val The value to align. + * @param Alignment The alignment value, can be any arbitrary value. + * + * @return The value aligned up to the specified alignment. + */ +template +FORCEINLINE T AlignArbitrary(T Val, uint64_t Alignment) +{ + return (T)((((uint64_t)Val + Alignment - 1) / Alignment) * Alignment); +} + +#pragma endregion + +// Align Toolkit +//////////////////////// + +#pragma endregion + +#pragma region About Functors + +#pragma region Less + +/////////////////// +// Less + +/** + * Binary predicate class for sorting elements in order. Assumes < operator is defined for the template type. + * Forward declaration exists in ContainersFwd.h + * + * See: http://en.cppreference.com/w/cpp/utility/functional/less + */ +struct TLess +{ + template + FORCEINLINE bool operator()(const T& A, const U& B) const + { + return A < B; + } +}; + +// Less +//////////////////// + +#pragma endregion + +#pragma region Greater + +//////////////////////// +// Greater + +/** + * Binary predicate class for sorting elements in reverse order. Assumes < operator is defined for the template type. + * + * See: http://en.cppreference.com/w/cpp/utility/functional/greater + */ +struct TGreater +{ + template + FORCEINLINE bool operator()(const T& A, const U& B) const + { + return B < A; + } +}; + +// Greater +////////////////////////// + +#pragma endregion + +#pragma region EqualTo + +///////////////////////////// +// EqualTo + +/** + * Binary predicate class for performing equality comparisons. + * + * Uses operator== when available. + * + * See: https://en.cppreference.com/w/cpp/utility/functional/equal_to + */ +struct TEqualTo +{ + template + constexpr auto operator()(const T& Lhs, const U& Rhs) const -> decltype(Lhs == Rhs) + { + return Lhs == Rhs; + } +}; + +// EqualTo +///////////////////////////// + +#pragma endregion + +#pragma region IdentityFunctor + +///////////////////////////// +// IdentityFunctor + +/** + * A functor which returns whatever is passed to it. Mainly used for generic composition. + */ +struct TIdentityFunctor +{ + template + FORCEINLINE T&& operator()(T&& Val) const + { + return (T&&)Val; + } +}; + +// IdentityFunctor +/////////////////////////////// + +#pragma endregion + +#pragma endregion + +#pragma region IntegralConstant + +/////////////////////////////// +// IntegralConstant + +/** + * Defines a value metafunction of the given Value. + */ +template +struct TIntegralConstant +{ + static constexpr T Value = Val; + + constexpr operator T() const + { + return Value; + } +}; + +// IntegralConstant +/////////////////////////////// + +#pragma endregion + #endif // !__FILE_Detail_CP_Arithmetic_Hpp diff --git a/detail/CP/CBool.hpp b/detail/CP/CBool.hpp index 282df8f..3ceb80c 100644 --- a/detail/CP/CBool.hpp +++ b/detail/CP/CBool.hpp @@ -18,13 +18,13 @@ namespace Internal template class CAnd_t; template class COr_t; - template<> class CAnd_t : public std::true_type {}; - template<> class CAnd_t : public std::false_type {}; + template< > class CAnd_t : public std::true_type {}; + template< > class CAnd_t : public std::false_type {}; template class CAnd_t : public CAnd_t {}; template class CAnd_t : public std::false_type {}; - template<> class COr_t : public std::true_type {}; - template<> class COr_t : public std::false_type {}; + template< > class COr_t : public std::true_type {}; + template< > class COr_t : public std::false_type {}; template class COr_t : public std::true_type {}; template class COr_t : public COr_t {}; } diff --git a/detail/CP/CHash.hpp b/detail/CP/CHash.hpp index df1803c..eff36a1 100644 --- a/detail/CP/CHash.hpp +++ b/detail/CP/CHash.hpp @@ -2,46 +2,50 @@ #ifndef __FILE_Detail_CP_CHash_Hpp #define __FILE_Detail_CP_CHash_Hpp +#ifndef FORCEINLINE +#define FORCEINLINE __forceinline +#endif // !FORCEINLINE + // // Hash functions for common types. // -inline uint32_t Hash(const uint8_t A) +FORCEINLINE uint32_t Hash(const uint8_t A) { return A; } -inline uint32_t Hash(const int8_t A) +FORCEINLINE uint32_t Hash(const int8_t A) { return A; } -inline uint32_t Hash(const uint16_t A) +FORCEINLINE uint32_t Hash(const uint16_t A) { return A; } -inline uint32_t Hash(const int16_t A) +FORCEINLINE uint32_t Hash(const int16_t A) { return A; } -inline uint32_t Hash(const int32_t A) +FORCEINLINE uint32_t Hash(const int32_t A) { return A; } -inline uint32_t Hash(const uint32_t A) +FORCEINLINE uint32_t Hash(const uint32_t A) { return A; } -inline uint32_t Hash(const uint64_t A) +FORCEINLINE uint32_t Hash(const uint64_t A) { return (uint32_t)A + ((uint32_t)(A >> 32) * 23); } -inline uint32_t Hash(const int64_t A) +FORCEINLINE uint32_t Hash(const int64_t A) { return (uint32_t)A + ((uint32_t)(A >> 32) * 23); } @@ -51,7 +55,8 @@ uint32_t Hash(const char* str, uint32_t hash = 5381) return *str == '\0' ? hash : Hash(str + 1, ((hash << 5) + hash) + *str); } -uint32_t Hash(std::string_view str, uint32_t hash = 5381) +template +uint32_t Hash(StringView str, uint32_t hash = 5381) { for (size_t i = 0; i < str.length(); ++i) { @@ -60,42 +65,53 @@ uint32_t Hash(std::string_view str, uint32_t hash = 5381) return hash; } -constexpr uint32_t CHash(const uint8_t A) +uint32_t THash(const char* const object, unsigned int length, uint32_t hash = 5381) +{ + return (length == 0) ? hash : THash(object + 1, length - 1, ((hash << 5) + hash) + *object); +} + +template +uint32_t THash(T* object, uint32_t hash = 5381) +{ + return THash((char*)object, sizeof(T), hash); +} + +FORCEINLINE constexpr uint32_t CHash(const uint8_t A) { return A; } -constexpr uint32_t CHash(const int8_t A) +FORCEINLINE constexpr uint32_t CHash(const int8_t A) { return A; } -constexpr uint32_t CHash(const uint16_t A) +FORCEINLINE constexpr uint32_t CHash(const uint16_t A) { return A; } -constexpr uint32_t CHash(const int16_t A) +FORCEINLINE constexpr uint32_t CHash(const int16_t A) { return A; } -constexpr uint32_t CHash(const int32_t A) +FORCEINLINE constexpr uint32_t CHash(const int32_t A) { return A; } -constexpr uint32_t CHash(const uint32_t A) +FORCEINLINE constexpr uint32_t CHash(const uint32_t A) { return A; } -constexpr uint32_t CHash(const uint64_t A) +FORCEINLINE constexpr uint32_t CHash(const uint64_t A) { return (uint32_t)A + ((uint32_t)(A >> 32) * 23); } -constexpr uint32_t CHash(const int64_t A) +FORCEINLINE constexpr uint32_t CHash(const int64_t A) { return (uint32_t)A + ((uint32_t)(A >> 32) * 23); } @@ -105,7 +121,8 @@ constexpr uint32_t CHash(const char* str, uint32_t hash = 5381) return *str == '\0' ? hash : CHash(str + 1, ((hash << 5) + hash) + *str); } -constexpr uint32_t CHash(std::string_view str, uint32_t hash = 5381) +template +constexpr uint32_t CHash(StringView str, uint32_t hash = 5381) { for (size_t i = 0; i < str.length(); ++i) { diff --git a/detail/CP/Typen.hpp b/detail/CP/Typen.hpp index de3002a..d86ffc1 100644 --- a/detail/CP/Typen.hpp +++ b/detail/CP/Typen.hpp @@ -2,14 +2,79 @@ #ifndef __FILE_Detail_CP_Typen_Hpp #define __FILE_Detail_CP_Typen_Hpp -#include "detail/CP/CHash.hpp" +#include "CHash.hpp" + +#pragma region TIdentity + +//////////////////////// +// TIdentity + +/** + * Returns the same type passed to it. This is useful in a few cases, but mainly for inhibiting template argument deduction in function arguments, e.g.: + * + * template + * void Func1(T Val); // Can be called like Func(123) or Func(123); + * + * template + * void Func2(typename TIdentity::Type Val); // Must be called like Func(123) + */ +template +struct TIdentity +{ + typedef T Type; +}; + +// TIdentity +////////////////////////// + +#pragma endregion template constexpr bool TIsBaseOf = std::is_base_of_v; -template constexpr bool TAreSame = std::is_same_v; +#pragma region TAreSame + +///////////////////////// +// TAreSame namespace Internal { + template struct TAreSameTool { static constexpr bool Value = false; }; + template struct TAreSameTool { static constexpr bool Value = true; }; +} + +template constexpr bool TAreSame = Internal::TAreSameTool::Value; + +// TAreSame +//////////////////////// + +#pragma endregion + +#pragma region Conditional Type + +/////////////////////////////// +// About Conditional + +namespace Internal +{ + /** Chooses between two different classes based on a boolean. */ + template + class TChooseClass; + + template + class TChooseClass + { + public: + typedef TrueClass Result; + }; + + template + class TChooseClass + { + public: + typedef FalseClass Result; + }; + + template struct TConditionalTool { @@ -32,27 +97,167 @@ namespace Internal template struct TConditionalTool { - using Type = std::conditional_t; + using Type = typename TChooseClass::Result; }; } template using TChoose = typename Internal::TConditionalTool::Type; template using TConditional = typename Internal::TConditionalTool::Type; -template using TDecay = std::decay_t; +// Conditional +/////////////////////////////// -template constexpr bool TIsP = std::is_pointer_v; -template constexpr bool TIsC = std::is_const_v; -template constexpr bool TIsV = std::is_volatile_v; -template constexpr bool TIsR = std::is_reference_v; -template constexpr bool TIsF = std::is_function_v; +#pragma endregion + +template constexpr bool TIsPointer = std::is_pointer_v; +template constexpr bool TIsConst = std::is_const_v; +template constexpr bool TIsVolatile = std::is_volatile_v; +template constexpr bool TIsRef = std::is_reference_v; +template constexpr bool TIsFunc = std::is_function_v; template constexpr bool TIsLR = std::is_lvalue_reference_v; template constexpr bool TIsRR = std::is_rvalue_reference_v; -template constexpr bool TIsCV = TIsC && TIsV; -template constexpr bool TIsIt = TIsP || TIsLR())>; -template constexpr bool TIsVoid = std::is_same_v; -template constexpr bool THasVirtual = std::has_virtual_destructor_v; -template constexpr bool TIsCStr = TAreSame&& TAreSame; +template constexpr bool TIsCV = TIsConst && TIsVolatile; +template constexpr bool TIsIt = TIsPointer || TIsLR())>; +template constexpr bool TIsVoid = TAreSame; +template constexpr bool TIsVirtual = std::has_virtual_destructor_v; +template constexpr bool TIsPolymorphic = std::is_polymorphic_v; +template constexpr bool TIsAbstract = std::is_abstract_v; +template constexpr bool TIsClass = std::is_class_v; +template constexpr bool TIsPOD = std::is_pod_v; +template constexpr bool TIsCStr = TAreSame && TAreSame; +template constexpr bool TIsConstructible = std::is_constructible_v; + +#pragma region About Enum + +template constexpr bool TIsEnum = std::is_enum_v; + +///////////////////////// +// TIsEnumClass + +namespace Internal +{ + template + struct TIsEnumConvertibleToIntTool + { + static char(&Resolve(int))[2]; + static char Resolve(...); + + enum { Value = sizeof(Resolve(T())) - 1 }; + }; +} + +/** + * Traits class which tests if a type is arithmetic. + */ + +template constexpr bool TIsEnumClass = TIsEnum && !Internal::TIsEnumConvertibleToIntTool; + +// TIsEnumClass +/////////////////////////// + +#pragma endregion + +#pragma region TIsTrivial + +///////////////////////// +// TIsTriviallyDestructible + +template constexpr bool TIsTriviallyDestructible = std::is_trivially_destructible_v; + +// TIsTriviallyDestructible +/////////////////////////// + +///////////////////////// +// TIsTriviallyCopyConstructible + +template constexpr bool TIsTriviallyCopyConstructible = std::is_trivially_constructible_v; + +// TIsTriviallyCopyConstructible +////////////////////////// + +////////////////////////// +// TIsTriviallyCopyAssignable + +template constexpr bool TIsTriviallyCopyAssignable = std::is_trivially_copyable_v; + +// TIsTriviallyCopyAssignable +/////////////////////////// + +/////////////////////////// +// TIsTrivial + +template constexpr bool TIsTrivial = std::is_trivial_v; + +// TIsTrivial +//////////////////////////// + +#pragma endregion + +#pragma region TIsMemberPointerTool + +/////////////////////////////// +// TIsMemberPointer + +namespace Internal +{ + /** + * Traits class which tests if a type is a pointer to member (data member or member function). + */ + template + struct TIsMemberPointerTool + { + constexpr static bool Value = false; + }; + + template struct TIsMemberPointerTool { constexpr static bool Value = true; }; + + template struct TIsMemberPointerTool { constexpr static bool Value = TIsMemberPointerTool::Value; }; + template struct TIsMemberPointerTool< volatile T> { constexpr static bool Value = TIsMemberPointerTool::Value; }; + template struct TIsMemberPointerTool { constexpr static bool Value = TIsMemberPointerTool::Value; }; +} + +template constexpr bool TIsMemberPointer = Internal::TIsMemberPointerTool::Value; + +// TIsMemberPointer +/////////////////////////////// + +#pragma endregion + +#pragma region TIsInitializerList + +//////////////////////////////////// +// TIsInitializerList + +namespace Internal +{ + /** + * Traits class which tests if a type is an initializer list. + */ + template + struct TIsInitializerListTool + { + static constexpr bool Value = false; + }; + + template + struct TIsInitializerListTool> + { + static constexpr bool Value = true; + }; + + template struct TIsInitializerListTool { static constexpr Value = TIsInitializerListTool::Value; }; + template struct TIsInitializerListTool< volatile T> { static constexpr Value = TIsInitializerListTool::Value; }; + template struct TIsInitializerListTool { static constexpr Value = TIsInitializerListTool::Value; }; +} + +template constexpr bool TIsInitializerList = Internal::TIsInitializerListTool::Value; + +// TIsInitializerList +//////////////////////////////////// + +#pragma endregion + +#pragma region Remove Type template using TRemoveP = std::remove_pointer_t; template using TRemoveC = std::remove_const_t; @@ -60,7 +265,205 @@ template using TRemoveV = std::remove_volatile_t; template using TRemoveR = std::remove_reference_t; template using TRemoveCV = std::remove_cv_t; -template using TEnableIf = std::enable_if_t; +#pragma endregion + +#pragma region About Array + +#pragma region IsArray + +/** + * Traits class which tests if a type is a C++ array. + */ +template struct TIsArray { constexpr static bool Value = false; }; +template struct TIsArray { constexpr static bool Value = true; }; +template struct TIsArray { constexpr static bool Value = true; }; + +/** + * Traits class which tests if a type is a bounded C++ array. + */ +template struct TIsBoundedArray { constexpr static bool Value = false; }; +template struct TIsBoundedArray { constexpr static bool Value = true; }; + +/** + * Traits class which tests if a type is an unbounded C++ array. + */ +template struct TIsUnboundedArray { constexpr static bool Value = false; }; +template struct TIsUnboundedArray { constexpr static bool Value = true; }; + +#pragma endregion + +#pragma region Ref Version + +/** + * Type trait which returns true if the type T is an array or a reference to an array of ArrType. + */ +template +struct TIsArrayOrRefOfType +{ + constexpr static bool Value = false; +}; + +template struct TIsArrayOrRefOfType< ArrType[], ArrType> { constexpr static bool Value = true; }; +template struct TIsArrayOrRefOfType { constexpr static bool Value = true; }; +template struct TIsArrayOrRefOfType< volatile ArrType[], ArrType> { constexpr static bool Value = true; }; +template struct TIsArrayOrRefOfType { constexpr static bool Value = true; }; + +template struct TIsArrayOrRefOfType< ArrType[N], ArrType> { constexpr static bool Value = true; }; +template struct TIsArrayOrRefOfType { constexpr static bool Value = true; }; +template struct TIsArrayOrRefOfType< volatile ArrType[N], ArrType> { constexpr static bool Value = true; }; +template struct TIsArrayOrRefOfType { constexpr static bool Value = true; }; + +template struct TIsArrayOrRefOfType< ArrType(&)[N], ArrType> { constexpr static bool Value = true; }; +template struct TIsArrayOrRefOfType { constexpr static bool Value = true; }; +template struct TIsArrayOrRefOfType< volatile ArrType(&)[N], ArrType> { constexpr static bool Value = true; }; +template struct TIsArrayOrRefOfType { constexpr static bool Value = true; }; + +#pragma endregion + + +#pragma endregion + +#pragma region TEnableIf + +//////////////////////// +// TEnableIf + +namespace Internal +{ + /** + * Includes a function in an overload set if the predicate is true. It should be used similarly to this: + * + * // This function will only be instantiated if SomeTrait::Value is true for a particular T + * template + * typename TEnableIf::Value, ReturnType>::Type Function(const T& Obj) + * { + * ... + * } + * + * ReturnType is the real return type of the function. + */ + template + class TEnableIfTool; + + template + class TEnableIfTool + { + public: + using type = Result; + using Type = Result; + }; + + template + class TEnableIfTool + { + }; + +} + +template using TEnableIf = typename Internal::TEnableIfTool::Type; + +// TEnableIf +//////////////////////// + +//////////////////////// +// TLazyEnableIf + +namespace Internal +{ + /** + * This is a variant of the above that will determine the return type 'lazily', i.e. only if the function is enabled. + * This is useful when the return type isn't necessarily legal code unless the enabling condition is true. + * + * // This function will only be instantiated if SomeTrait::Value is true for a particular T. + * // The function's return type is typename Transform::Type. + * template + * typename TLazyEnableIf::Value, Transform>::Type Function(const T& Obj) + * { + * ... + * } + * + * See boost::lazy_enable_if for more details. + */ + template + class TLazyEnableIfTool; + + template + class TLazyEnableIfTool + { + public: + using type = typename Func::Type; + using Type = typename Func::Type; + }; + + template + class TLazyEnableIfTool + { + }; +} + +template using TLazyEnableIf = Internal::TLazyEnableIfTool; + +// TLazyEnableIf +//////////////////////// + +#pragma endregion + +#pragma region TDecay + +///////////////////// +// TDeacy + +namespace Internal +{ + template + struct TDecayNonReference + { + using Type = TRemoveCV; + }; + + template + struct TDecayNonReference + { + using Type = T*; + }; + + template + struct TDecayNonReference + { + using Type = T*; + }; + + template + struct TDecayNonReference + { + using Type = RetType(*)(Params...); + }; + + + /** + * Returns the decayed type of T, meaning it removes all references, qualifiers and + * applies array-to-pointer and function-to-pointer conversions. + * + * http://en.cppreference.com/w/cpp/types/decay + */ + template + struct TDecayTool + { + typedef typename TDecayNonReference::Type>::Type Type; + }; +} + +template using TDecay = typename Internal::TDecayTool::Type; + +// TDeacy +////////////////////// + +#pragma endregion + +#pragma region THasToString + +//////////////////////////// +// THasToString namespace Internal { @@ -127,6 +530,16 @@ namespace Internal template constexpr bool THasToString = Internal::StringAbleTool::Value; +// THasToString +//////////////////////////// + +#pragma endregion + +#pragma region TIsConvertible + +///////////////////////////// +// TIsConvertible + namespace Internal { template @@ -145,6 +558,16 @@ template constexpr bool TIsConvertible = Internal:: template constexpr bool TIsPointerConvertible = TIsConvertible; template constexpr bool TIsReferenceConvertible = TIsConvertible; +// TIsConvertible +///////////////////////////// + +#pragma endregion + +#pragma region TCopyQualifiers + +/////////////////////////////// +// TCopyQualifiers + namespace Internal { /** @@ -161,10 +584,73 @@ namespace Internal template using TCopyQualifiers = typename Internal::TCopyQualifiersTool::Type; -template constexpr bool TLosesQualifiers = !TAreSame, To>; +// TCopyQualifiers +//////////////////////////////// + +//////////////////////////////// +// TCopyQualifiersAndRefs namespace Internal { + /** + * Copies the cv-qualifiers and references from one type to another + */ + template struct TCopyQualifiersAndRefsTool { using Type = typename TCopyQualifiersTool::Type; }; + template struct TCopyQualifiersAndRefsTool { using Type = typename TCopyQualifiersTool::Type&; }; + template struct TCopyQualifiersAndRefsTool { using Type = typename TCopyQualifiersTool::Type&&; }; + template struct TCopyQualifiersAndRefsTool { using Type = typename TCopyQualifiersTool::Type&; }; + template struct TCopyQualifiersAndRefsTool { using Type = typename TCopyQualifiersTool::Type&; }; + template struct TCopyQualifiersAndRefsTool { using Type = typename TCopyQualifiersTool::Type&; }; + template struct TCopyQualifiersAndRefsTool { using Type = typename TCopyQualifiersTool::Type&&; }; + template struct TCopyQualifiersAndRefsTool { using Type = typename TCopyQualifiersTool::Type&; }; + template struct TCopyQualifiersAndRefsTool { using Type = typename TCopyQualifiersTool::Type&&; }; +} + +template using TCopyQualifiersAndRefsFromTo_T = typename Internal::TCopyQualifiersAndRefsTool::Type; + +// TCopyQualifiersAndRefs +//////////////////////////////// + +template constexpr bool TLosesQualifiers = !TAreSame, To>; + +#pragma endregion + +#pragma region TLosesQualifiersFromTo + +/////////////////////// +// TLosesQualifiersFromTo + +namespace Internal +{ + /** + * Tests if qualifiers are lost between one type and another, e.g.: + * + * TLosesQualifiersFromTo::Value == true + * TLosesQualifiersFromTo::Value == false + */ + template + struct TLosesQualifiersFromToTool + { + constexpr static bool Value = !TAreSame, To>; + }; +} + +template using TLosesQualifiersFromTo = Internal::TLosesQualifiersFromToTool; + +// TLosesQualifiersFromTo +/////////////////////////// + +#pragma endregion + +#pragma region TTrait + +////////////////////// +// TTrait + +namespace Internal +{ +#pragma region Tools + struct PrettyFunctionTag {}; template @@ -255,9 +741,30 @@ namespace Internal return name; } +#pragma endregion + template struct TraitTool; template struct TraitTool { + public: + constexpr static bool IsPointer = TIsPointer; + constexpr static bool IsRef = TIsRef; + constexpr static bool IsVoid = TIsVoid; + constexpr static bool IsVirtual = TIsVirtual; + constexpr static bool IsPolymorphic = TIsPolymorphic; + constexpr static bool IsAbstract = TIsAbstract; + constexpr static bool IsClass = TIsClass; + constexpr static bool IsPOD = TIsPOD; + constexpr static bool IsEnum = TIsEnum; + constexpr static bool IsEnumClass = TIsEnum; + constexpr static bool IsTriviallyDestructible = TIsTriviallyDestructible; + constexpr static bool IsTriviallyCopyConstructible = TIsTriviallyCopyConstructible; + constexpr static bool IsTriviallyCopyAssignable = TIsTriviallyCopyAssignable; + constexpr static bool IsTrivial = TIsTrivial; + constexpr static bool IsMemberPointer = TIsMemberPointer; + constexpr static bool IsInitializerList = TIsInitializerList; + constexpr static bool HasToString = THasToString; + public: template static constexpr bool Is() { return (TAreSame || (Derived && TIsBaseOf)); } template static constexpr bool Is(P) { return (TAreSame || (Derived && TIsBaseOf)); } template static constexpr bool Is(P from, T& to) @@ -275,10 +782,13 @@ namespace Internal static auto symbol = typeid(T).hash_code(); return (intptr_t)&symbol; } + + constexpr static uint32_t NewPtrMemorySize = sizeof(decltype(Symbol())) + sizeof(T); + static T* New(void* memory, size_t capacity) { using TSymbol = decltype(Symbol()); - constexpr auto size = sizeof(TSymbol) + sizeof(T); + constexpr auto size = NewPtrMemorySize; if (capacity < size || memory == nullptr) return nullptr; char* ptr = new(memory) char[size]; @@ -445,10 +955,18 @@ namespace Internal static uint32_t Hash(const T& v) { if constexpr (std::is_integral_v) - return GetTypeHash(v); + return Hash(v); else - return GetTypeHash(&v); + return THash(&v); } + static uint32_t Hash(T* v) + { + if constexpr (std::is_integral_v) + return Hash(*v); + else + return THash(v); + } + private: constexpr static uint32_t InjectTypeHash() { @@ -473,44 +991,85 @@ namespace Internal template using TTrait = Internal::TraitTool>; +// TTrait +//////////////////////// + +//////////////////////// +// ValueTrait + namespace Internal { template class ValueClass : public TTrait { private: - T value; using _Mybase = TTrait; + char MyMemoryInside[NewPtrMemorySize]; + T* MyCachePtr; public: - ValueClass(const T& value) : value(value) {} - ValueClass(T& value) : value(value) {} - ValueClass(T&& value) : value(std::move(value)) {} - ValueClass& operator=(const T& value) noexcept + template>> + ValueClass() { - this->value = value; + MyCachePtr = _Mybase::New(MyMemoryInside, NewPtrMemorySize); + new(MyCachePtr) T(); } - ValueClass& operator=(T& value) noexcept + template>> + ValueClass(First first) { - this->value = value; + MyCachePtr = _Mybase::New(MyMemoryInside, NewPtrMemorySize); + new(MyCachePtr) T(first); } - ValueClass& operator=(T&& value) noexcept + template>> + ValueClass(First first, Second second) { - this->value = std::move(value); + MyCachePtr = _Mybase::New(MyMemoryInside, NewPtrMemorySize); + new(MyCachePtr) T(first, second); } + template>> + ValueClass(First first, Second second, Third third) + { + MyCachePtr = _Mybase::New(MyMemoryInside, NewPtrMemorySize); + new(MyCachePtr) T(first, second, third); + } + template>> + ValueClass(First first, Second second, Third third, Other other) + { + MyCachePtr = _Mybase::New(MyMemoryInside, NewPtrMemorySize); + new(MyCachePtr) T(first, second, third, other); + } + + T& ReadValue() + { + return *MyCachePtr; + } + + const T& ReadValue() const + { + return *MyCachePtr; + } + constexpr operator T& () { - return value; + return *MyCachePtr; } + constexpr operator const T& () const { - return value; + return *MyCachePtr; } + uint32_t Hash() { - return _Mybase::Hash(value); + return _Mybase::Hash(MyCachePtr); } }; } +// ValueTrait +//////////////////////// + using Bool = Internal::ValueClass; using Int = Internal::ValueClass; using Float = Internal::ValueClass; @@ -527,36 +1086,34 @@ using UInt32 = Internal::ValueClass; using UInt64 = Internal::ValueClass; using LongDouble = Internal::ValueClass; -#if !defined(nameofT)&&!defined(nameofEnum) -template constexpr auto __Inject_nameof() +#pragma endregion + +#pragma region nameof + +namespace Internal { - return TTrait::SymbolName(); + template constexpr auto __Inject_nameof_type() + { + return TTrait::SymbolName(); + } + template constexpr auto __Inject_nameof_value() + { + return TTrait::ValueName(); + } } -template constexpr auto __Inject_nameof() -{ - return TTrait::ValueName(); -} -#define nameofT(x) __Inject_nameof(); -#define nameofEnum(x) __Inject_nameof(); -#else -template constexpr auto nameof() -{ - return TTrait::SymbolName(); -} -template constexpr auto nameof() -{ - return TTrait::ValueName(); -} -#endif // !nameof +#define nameof(x) Internal::__Inject_nameof_type(); +#define nameofEnum(x) Internal::__Inject_nameof_value(); + +#pragma endregion -template using TUnwrapped = TEnableIf, TConditional, TRemoveP, decltype(*std::declval())>>; +template using TUnwrapped = TEnableIf, TConditional, TRemoveP, decltype(*std::declval())>>; template > decltype(auto) Unwrapping(T from) { return *from; } -template > || TIsConvertible> To Cast(From data) +template , To> || TIsConvertible> To Cast(From data) { if constexpr (TIsConvertible) return static_cast(data);