feat(typetraits): add TypeTraits/Miscellaneous.h and the corresponding testing

This commit is contained in:
_Redstone_c_ 2021-12-22 23:24:25 +08:00
parent c37f2c3153
commit 97fbe0fc84
2 changed files with 208 additions and 1 deletions

View File

@ -5,6 +5,7 @@
#include "TypeTraits/CompositeType.h"
#include "TypeTraits/TypeProperties.h"
#include "TypeTraits/SupportedOperations.h"
#include "TypeTraits/Miscellaneous.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
@ -16,7 +17,7 @@ int32 TestObject;
void TestFunction() { }
struct FTestStructA { };
struct FTestStructB { int32 Member; };
struct FTestStructB : FTestStructA { int32 Member; };
struct FTestStructC { FTestStructC() { } };
struct FTestStructD { FTestStructD(const FTestStructD&) { } };
struct FTestStructE { virtual void Member() = 0; };
@ -37,9 +38,13 @@ struct FTestStructS { int32 MemberA; double MemberB; ~FTestStructS() { } };
struct FTestStructT { int32 MemberA; double MemberB; ~FTestStructT() = default; };
struct FTestStructU { int32 MemberA; double MemberB; ~FTestStructU() = delete; };
struct FTestStructV { int32 MemberA; double MemberB; virtual ~FTestStructV() { }; };
struct FTestStructW { int32 MemberA; double MemberB; operator FTestStructV() { return FTestStructV(); } };
enum ETestEnum { };
enum class ETestEnumClass { };
enum class ETestEnumClass8 : uint8 { };
enum class ETestEnumClass32 : uint32 { };
enum class ETestEnumClass64 : uint64 { };
union FTestUnion { };
@ -301,6 +306,146 @@ void TestTypeTraits()
always_check(!TypeTraits::THasVirtualDestructor<FTestStructT>::Value);
always_check(TypeTraits::THasVirtualDestructor<FTestStructV>::Value);
// Miscellaneous.h
always_check(TypeTraits::TRank<int32[1][2][3]>::Value == 3);
always_check(TypeTraits::TRank<int32[1][2][3][4]>::Value == 4);
always_check(TypeTraits::TRank<int32>::Value == 0);
always_check(TypeTraits::TExtent<int32[1][2][3]>::Value == 1);
always_check((TypeTraits::TExtent<int32[1][2][3][4], 1>::Value == 2));
always_check(TypeTraits::TExtent<int32[]>::Value == 0);
always_check(!(TypeTraits::TIsSame<int32, int64>::Value));
always_check((TypeTraits::TIsSame<int32, int32>::Value));
always_check(!(TypeTraits::TIsBaseOf<FTestStructH, FTestStructD>::Value));
always_check(!(TypeTraits::TIsBaseOf<FTestStructH, FTestStructE>::Value));
always_check((TypeTraits::TIsBaseOf<FTestStructE, FTestStructH>::Value));
always_check((TypeTraits::TIsConvertible<int32, uint32>::Value));
always_check(!(TypeTraits::TIsConvertible<FTestStructH*, FTestStructD*>::Value));
always_check((TypeTraits::TIsConvertible<FTestStructH*, FTestStructE*>::Value));
always_check(!(TypeTraits::TIsConvertible<FTestStructE*, FTestStructH*>::Value));
always_check((TypeTraits::TIsConvertible<FTestStructW, FTestStructV>::Value));
always_check((TypeTraits::TIsInvocable<void, int32()>::Value));
always_check((TypeTraits::TIsInvocable<int32, int32()>::Value));
always_check((TypeTraits::TIsInvocable<int32, int32(int32), int32>::Value));
always_check(!(TypeTraits::TIsInvocable<int32, int32(int32), FTestStructA>::Value));
always_check(!(TypeTraits::TIsInvocable<FTestStructA, int32(int32), int32>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveConst<int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveConst<int32*>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveConst<int32&>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveConst<int32&&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveConst<const int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveConst<volatile int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveConst<const volatile int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveConst<const volatile int32&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveVolatile<int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveVolatile<int32*>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveVolatile<int32&>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveVolatile<int32&&>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveVolatile<const int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveVolatile<volatile int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveVolatile<const volatile int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveVolatile<const volatile int32&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveCV<int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveCV<int32*>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveCV<int32&>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveCV<int32&&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveCV<const int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveCV<volatile int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveCV<const volatile int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveCV<const volatile int32&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemovePointer<int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemovePointer<int32*>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemovePointer<int32&>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemovePointer<int32&&>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemovePointer<const int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemovePointer<volatile int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemovePointer<const volatile int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemovePointer<const volatile int32&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveReference<int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveReference<int32*>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveReference<int32&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveReference<int32&&>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveReference<const int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveReference<volatile int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveReference<const volatile int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveReference<const volatile int32&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveCVRef<int32>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveCVRef<int32*>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveCVRef<int32&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveCVRef<int32&&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveCVRef<const int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveCVRef<volatile int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveCVRef<const volatile int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveCVRef<const volatile int32&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveExtent<int32[1]>::Type>::Value));
always_check(!(TypeTraits::TIsSame<int32, TypeTraits::TRemoveExtent<int32[1][2]>::Type>::Value));
always_check((TypeTraits::TIsSame<int32[2][3], TypeTraits::TRemoveExtent<int32[1][2][3]>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveAllExtents<int32[1]>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveAllExtents<int32[1][2]>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TRemoveAllExtents<int32[1][2][3]>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TMakeSigned<int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TMakeSigned<uint32>::Type>::Value));
always_check((TypeTraits::TIsSame<uint32, TypeTraits::TMakeUnsigned<int32>::Type>::Value));
always_check((TypeTraits::TIsSame<uint32, TypeTraits::TMakeUnsigned<uint32>::Type>::Value));
TypeTraits::TAlignedStorage<32, 4>::Type Aligned4;
TypeTraits::TAlignedStorage<32, 8>::Type Aligned8;
TypeTraits::TAlignedStorage<32, 16>::Type Aligned16;
TypeTraits::TAlignedStorage<32, 32>::Type Aligned32;
always_check((int64)(&Aligned4) % 4 == 0);
always_check((int64)(&Aligned8) % 8 == 0);
always_check((int64)(&Aligned16) % 16 == 0);
always_check((int64)(&Aligned32) % 32 == 0);
always_check(sizeof(TypeTraits::TAlignedUnion<8, int32, int32>::Type) == 8);
always_check(sizeof(TypeTraits::TAlignedUnion<0, int8, int32>::Type) == 4);
always_check(sizeof(TypeTraits::TAlignedUnion<0, int32, int64>::Type) == 8);
always_check(sizeof(TypeTraits::TAlignedUnion<0, int32, double>::Type) == 8);
always_check((TypeTraits::TIsSame<int32, TypeTraits::TDecay<int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32*, TypeTraits::TDecay<int32*>::Type>::Value));
always_check((TypeTraits::TIsSame<int32*, TypeTraits::TDecay<int32[]>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TDecay<int32&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TDecay<int32&&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TDecay<const int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TDecay<volatile int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TDecay<const volatile int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TDecay<const volatile int32&>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TConditional<true, int32, int64>::Type>::Value));
always_check((TypeTraits::TIsSame<int64, TypeTraits::TConditional<false, int32, int64>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TCommonType<int8, int32>::Type>::Value));
always_check((TypeTraits::TIsSame<int64, TypeTraits::TCommonType<int8, int32, int64>::Type>::Value));
always_check((TypeTraits::TIsSame<double, TypeTraits::TCommonType<float, double>::Type>::Value));
always_check((TypeTraits::TIsSame<int, TypeTraits::TUnderlyingType<ETestEnumClass>::Type>::Value));
always_check((TypeTraits::TIsSame<uint8, TypeTraits::TUnderlyingType<ETestEnumClass8>::Type>::Value));
always_check((TypeTraits::TIsSame<uint32, TypeTraits::TUnderlyingType<ETestEnumClass32>::Type>::Value));
always_check((TypeTraits::TIsSame<uint64, TypeTraits::TUnderlyingType<ETestEnumClass64>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TInvokeResult<int32()>::Type>::Value));
always_check((TypeTraits::TIsSame<int32, TypeTraits::TInvokeResult<int32(int32), int32>::Type>::Value));
always_check((TypeTraits::TIsSame<void, TypeTraits::TVoid<int32>::Type>::Value));
always_check((TypeTraits::TIsSame<void, TypeTraits::TVoid<int32, int64>::Type>::Value));
}
NAMESPACE_MODULE_END(Utility)

View File

@ -0,0 +1,62 @@
#pragma once
#include "CoreTypes.h"
#include "TypeTraits/HelperClasses.h"
#include <type_traits>
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_BEGIN(TypeTraits)
NAMESPACE_PRIVATE_BEGIN
template <size_t... Values>
struct TMaximum;
template <>
struct TMaximum<> : TConstant<size_t, 0> { };
template <size_t Value>
struct TMaximum<Value> : TConstant<size_t, Value> { };
template <size_t First, size_t Second, size_t... Others>
struct TMaximum<First, Second, Others...> : TMaximum<(First < Second ? Second : First), Others...> { };
NAMESPACE_PRIVATE_END
template <typename T> struct TRank : TConstant<size_t, NAMESPACE_STD::rank_v<T>> { };
template <typename T, size_t I = 0> struct TExtent : TConstant<size_t, NAMESPACE_STD::extent_v<T, I>> { };
template <typename T, typename U> struct TIsSame : TBoolConstant<NAMESPACE_STD::is_same_v<T, U>> { };
template <typename T, typename U> struct TIsBaseOf : TBoolConstant<NAMESPACE_STD::is_base_of_v<T, U>> { };
template <typename T, typename U> struct TIsConvertible : TBoolConstant<NAMESPACE_STD::is_convertible_v<T, U>> { };
template <typename R, typename F, typename... Args> struct TIsInvocable : TBoolConstant<NAMESPACE_STD::is_invocable_r_v<R, F, Args...>> { };
template <typename T> struct TRemoveConst { using Type = NAMESPACE_STD::remove_const_t<T>; };
template <typename T> struct TRemoveVolatile { using Type = NAMESPACE_STD::remove_volatile_t<T>; };
template <typename T> struct TRemoveCV { using Type = NAMESPACE_STD::remove_cv_t<T>; };
template <typename T> struct TRemovePointer { using Type = NAMESPACE_STD::remove_pointer_t<T>; };
template <typename T> struct TRemoveReference { using Type = NAMESPACE_STD::remove_reference_t<T>; };
template <typename T> struct TRemoveCVRef { using Type = NAMESPACE_STD::remove_cvref_t<T>; };
template <typename T> struct TRemoveExtent { using Type = NAMESPACE_STD::remove_extent_t<T>; };
template <typename T> struct TRemoveAllExtents { using Type = NAMESPACE_STD::remove_all_extents_t<T>; };
template <typename T> struct TMakeSigned { using Type = NAMESPACE_STD::make_signed_t<T>; };
template <typename T> struct TMakeUnsigned { using Type = NAMESPACE_STD::make_unsigned_t<T>; };
template <size_t Size, size_t Align> struct TAlignedStorage { class Type { struct alignas(Align) { uint8 Pad[Size]; } Padding; }; };
template <size_t Size, typename... Types> struct TAlignedUnion { using Type = TAlignedStorage<NAMESPACE_PRIVATE::TMaximum<Size, sizeof(Types)...>::Value, NAMESPACE_PRIVATE::TMaximum<alignof(Types)...>::Value>::Type; };
template <typename T> struct TDecay { using Type = NAMESPACE_STD::decay_t<T>; };
template <bool B, typename T = void> struct TEnableIf { using Type = NAMESPACE_STD::enable_if_t<B, T>; };
template <bool B, typename T, typename F> struct TConditional { using Type = NAMESPACE_STD::conditional_t<B, T, F>; };
template <typename... Types> struct TCommonType { using Type = NAMESPACE_STD::common_type_t<Types...>; };
template <typename T> struct TUnderlyingType { using Type = NAMESPACE_STD::underlying_type_t<T>; };
template <typename F, typename... Args> struct TInvokeResult { using Type = NAMESPACE_STD::invoke_result_t<F, Args...>; };
template <typename... Types> struct TVoid { using Type = void; };
NAMESPACE_END(TypeTraits)
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END