#pragma once #ifndef __FILE_Detail_CP_Typen_Hpp #define __FILE_Detail_CP_Typen_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; #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 { }; template struct TConditionalTool { using Type = typename TConditionalTool::Type; }; template struct TConditionalTool { using Type = First; }; template struct TConditionalTool { using Type = First; }; template struct TConditionalTool { using Type = typename TChooseClass::Result; }; } template using TChoose = typename Internal::TConditionalTool::Type; template using TConditional = typename Internal::TConditionalTool::Type; // Conditional /////////////////////////////// #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 = 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; template using TRemoveV = std::remove_volatile_t; template using TRemoveR = std::remove_reference_t; template using TRemoveCV = std::remove_cv_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 { template struct StringAbleTool { template ()))> static constexpr bool check_std_to_string(U*) { return true; } template static constexpr bool check_std_to_string(...) { return false; } template ()))> static constexpr bool check_to_string(U*) { return true; } template static constexpr bool check_to_string(...) { return false; } template ().ToString)> static constexpr bool check_self_to_string(U*) { return true; } template static constexpr bool check_self_to_string(...) { return false; } static constexpr bool Value = check_std_to_string(nullptr) || check_to_string(nullptr) || check_self_to_string(nullptr); template ()))> static constexpr bool check_atoi_parse(U*) { return true; } template static constexpr bool check_atoi_parse(...) { return true; } template ()))> static constexpr bool check_atof_parse(U*) { return true; } template static constexpr bool check_atof_parse(...) { return true; } template ()))> static constexpr bool check_atol_parse(U*) { return true; } template static constexpr bool check_atol_parse(...) { return true; } template ()))> static constexpr bool check_atoll_parse(U*) { return true; } template static constexpr bool check_atoll_parse(...) { return true; } template (),(const char*const)nullptr,0))> static constexpr bool check_parse_string(U*) { return true; } template static constexpr bool check_parse_string(...) { return false; } template ().Parse((const char* const)nullptr, 0))> static constexpr bool check_self_parse(U*) { return true; } template static constexpr bool check_self_parse(...) { return false; } }; } template constexpr bool THasToString = Internal::StringAbleTool::Value; // THasToString //////////////////////////// #pragma endregion #pragma region TIsConvertible ///////////////////////////// // TIsConvertible namespace Internal { template struct TIsConvertibleImpl { private: static uint_fast8_t Test(...); static uint_fast16_t Test(To); public: enum { Value = sizeof(Test((From)std::declval())) - 1 }; }; } template constexpr bool TIsConvertible = Internal::TIsConvertibleImpl::Value; template constexpr bool TIsPointerConvertible = TIsConvertible; template constexpr bool TIsReferenceConvertible = TIsConvertible; // TIsConvertible ///////////////////////////// #pragma endregion #pragma region TCopyQualifiers /////////////////////////////// // TCopyQualifiers namespace Internal { /** * Copies the cv-qualifiers from one type to another, e.g.: * * TCopyQualifiers::Type == const T2 * TCopyQualifiers::Type == const volatile T2 */ template struct TCopyQualifiersTool { typedef To Type; }; template struct TCopyQualifiersTool { typedef const To Type; }; template struct TCopyQualifiersTool< volatile From, To> { typedef volatile To Type; }; template struct TCopyQualifiersTool { typedef const volatile To Type; }; } template using TCopyQualifiers = typename Internal::TCopyQualifiersTool::Type; // 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 constexpr std::string_view PrettyFunction() { return __FUNCSIG__; } template constexpr std::string_view PrettyFunction() { return __FUNCSIG__; } constexpr size_t GetPrettyFunctionPrefix() { auto a = PrettyFunction(); auto b = PrettyFunction(); size_t result = 0; size_t end = std::min(a.size(), b.size()); for (; result < end; result++) { if (a.substr(0, result) != b.substr(0, result)) return result; } return result; } constexpr size_t GetPrettyFunctionSuffix() { auto a = PrettyFunction(); auto b = PrettyFunction(); size_t result = 0; size_t end = std::min(a.size(), b.size()); for (; result < end; result++) { if (a.substr(a.size() - result - 1, end) != b.substr(b.size() - result - 1, end)) return result; } return result; } template constexpr size_t GetPrettyFunctionWithValuePrefix() { auto a = PrettyFunction(0)>(); auto b = PrettyFunction(1)>(); size_t result = 0; size_t end = std::min(a.size(), b.size()); for (; result < end; result++) { if (a.substr(0, result) != b.substr(0, result)) return result; } return result; } template constexpr size_t GetPrettyFunctionWithValueSuffix() { auto a = PrettyFunction(0)>(); auto b = PrettyFunction(1)>(); size_t result = 0; size_t end = std::min(a.size(), b.size()); for (; result < end; result++) { if (a.substr(a.size() - result - 1, end) != b.substr(b.size() - result - 1, end)) return result; } return result; } template constexpr std::string_view SymbolNameTool() { auto name = PrettyFunction(); name.remove_prefix(GetPrettyFunctionPrefix() - 1); name.remove_suffix(GetPrettyFunctionSuffix()); return name; } template constexpr std::string_view ValueNameTool() { auto name = PrettyFunction(); name.remove_prefix(GetPrettyFunctionWithValuePrefix() - 1); name.remove_suffix(GetPrettyFunctionWithValueSuffix()); 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) { to = static_cast(from); return (TAreSame || (Derived && TIsBaseOf)); } static bool Is(void* ptr) { using TSymbol = decltype(Symbol()); return Symbol() == *reinterpret_cast(reinterpret_cast(ptr) - sizeof(TSymbol)); } static intptr_t Symbol() { 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 = NewPtrMemorySize; if (capacity < size || memory == nullptr) return nullptr; char* ptr = new(memory) char[size]; auto&& head = reinterpret_cast(*ptr); head = Symbol(); T* result = reinterpret_cast(&(ptr[sizeof(TSymbol)])); return result; } static void Delete(T* ptr) { using TSymbol = decltype(Symbol()); *reinterpret_cast(reinterpret_cast(ptr) - sizeof(TSymbol)) = 0; ptr->~T(); } static T* FirstInMemory(void* memory, size_t capacity) { for (char* head = (char*)memory, *end = (char*)memory + capacity; head != end; head++) { if (Is(head)) return (T*)head; } return nullptr; } static bool WriteBinary(T* object, char* buffer, size_t capacity) { if (sizeof(T) + sizeof(decltype(Symbol())) > capacity) return false; *reinterpret_cast(&buffer[0]) = Symbol(); memcpy_s(&buffer[sizeof(decltype(Symbol()))], capacity, object, sizeof(T)); return true; } static bool Write(T* object, char* buffer, size_t capacity, bool is_allow_binary_write = false) { if constexpr (StringAbleTool::check_self_to_string(nullptr)) { auto str = object->ToString(); size_t strCsize = 0; if constexpr (TIsCStr) { constexpr auto _strCsize = sizeof(decltype(*str[0])); strCsize = _strCsize; } else { constexpr auto _strCsize = sizeof(decltype(*str.begin())); strCsize = _strCsize; } if (strCsize == 0) return false; if (str.size() * strCsize > capacity) return false; memcpy_s(buffer, capacity, str.c_str(), str.size() * strCsize); } else if constexpr (StringAbleTool::check_to_string(nullptr)) { auto str = to_string(*object); size_t strCsize = 0; if constexpr (TIsCStr) { constexpr auto _strCsize = sizeof(decltype(*str[0])); strCsize = _strCsize; } else { constexpr auto _strCsize = sizeof(decltype(*str.begin())); strCsize = _strCsize; } if (strCsize == 0) return false; if (str.size() * strCsize > capacity) return false; memcpy_s(buffer, capacity, str.c_str(), str.size() * strCsize); } else if constexpr (StringAbleTool::check_std_to_string(nullptr)) { std::string str = std::to_string(*object); if (str.size() > capacity) return false; memcpy_s(buffer, capacity, str.c_str(), str.size()); } else { if (is_allow_binary_write == false) return false; WriteBinary(object, buffer, capacity); } return true; } static T* ReadBinaryWithoutToken(T* object, char* buffer, size_t capacity) { constexpr auto offset = sizeof(decltype(Symbol())); if (capacity > sizeof(T) + offset && *reinterpret_cast(&buffer[0]) == Symbol()) memcpy(object, &buffer[offset], capacity); else { if (capacity > sizeof(T)) memcpy(object, buffer, capacity); else return nullptr; } return object; } static T* ReadBinary(void* memory, size_t capacity, char* buffer, size_t buffer_capacity) { constexpr auto size = sizeof(T) + sizeof(decltype(Symbol())); if (size > buffer_capacity) return nullptr; if (size > capacity) return nullptr; if (*reinterpret_cast(&buffer[0]) != Symbol()) return nullptr; T* object = reinterpret_cast(&buffer[sizeof(decltype(Symbol()))]); memcpy(memory, buffer, size); return object; } static bool Parse(T* object, const char* const buffer, size_t capacity) { if constexpr (StringAbleTool::check_self_parse(nullptr)) { object->Parse(buffer, capacity); } else if constexpr (StringAbleTool::check_parse_string(nullptr)) { from_string(object, buffer, capacity); } else if constexpr (TAreSame) { if (strcmp(buffer, "true") == 0) *object = true; else if (strcmp(buffer, "false") == 0) *object = false; else return false; } else if constexpr (StringAbleTool::check_atoll_parse(nullptr)) { *object = static_cast(atoll(buffer)); } else if constexpr (StringAbleTool::check_atol_parse(nullptr)) { *object = static_cast(atol(buffer)); } else if constexpr (StringAbleTool::check_atoi_parse(nullptr)) { *object = static_cast(atoi(buffer)); } else if constexpr (StringAbleTool::check_atof_parse(nullptr)) { *object = static_cast(atof(buffer)); } else { return false; } return true; } constexpr static std::string_view SymbolName() { return SymbolNameTool(); } static uint32_t Hash(const T& v) { if constexpr (std::is_integral_v) return Hash(v); else 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() { auto str = SymbolName(); return CHash(str.data()); } public: constexpr static int TypeHash = InjectTypeHash(); }; template struct TraitTool : public TraitTool { template constexpr static std::string_view ValueName() { return ValueNameTool(); } }; template struct TraitTool : public TraitTool {}; template struct TraitTool< volatile T, IsIntegral> : public TraitTool {}; template struct TraitTool : public TraitTool {}; } template using TTrait = Internal::TraitTool>; // TTrait //////////////////////// //////////////////////// // ValueTrait namespace Internal { template class ValueClass : public TTrait { private: using _Mybase = TTrait; char MyMemoryInside[NewPtrMemorySize]; T* MyCachePtr; public: template>> ValueClass() { MyCachePtr = _Mybase::New(MyMemoryInside, NewPtrMemorySize); new(MyCachePtr) T(); } template>> ValueClass(First first) { MyCachePtr = _Mybase::New(MyMemoryInside, NewPtrMemorySize); new(MyCachePtr) T(first); } template>> ValueClass(First first, Second second) { 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 *MyCachePtr; } constexpr operator const T& () const { return *MyCachePtr; } uint32_t Hash() { return _Mybase::Hash(MyCachePtr); } }; } // ValueTrait //////////////////////// using Bool = Internal::ValueClass; using Int = Internal::ValueClass; using Float = Internal::ValueClass; using Double = Internal::ValueClass; using Long = Internal::ValueClass; using UInt = Internal::ValueClass; using Int8 = Internal::ValueClass; using Int16 = Internal::ValueClass; using Int32 = Internal::ValueClass; using Int64 = Internal::ValueClass; using UInt8 = Internal::ValueClass; using UInt16 = Internal::ValueClass; using UInt32 = Internal::ValueClass; using UInt64 = Internal::ValueClass; using LongDouble = Internal::ValueClass; #pragma endregion #pragma region nameof namespace Internal { template constexpr auto __Inject_nameof_type() { return TTrait::SymbolName(); } template constexpr auto __Inject_nameof_value() { return TTrait::ValueName(); } } #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 > decltype(auto) Unwrapping(T from) { return *from; } template , To> || TIsConvertible> To Cast(From data) { if constexpr (TIsConvertible) return static_cast(data); return static_cast(Unwrapping(data)); } #endif // !__FILE_Detail_CP_Typen_Hpp