/* * Copyright (c) 2020-2021, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #define STATIC_EXPECT_EQ(lhs, rhs) \ static_assert(IsSame, ""); #define STATIC_EXPECT_FALSE(Expression) \ static_assert(!Expression, ""); #define STATIC_EXPECT_TRUE(Expression) \ static_assert(Expression, ""); #define EXPECT_TRAIT_TRUE(trait, ...) \ for_each_type>([](TypeWrapper) { \ STATIC_EXPECT_TRUE(trait); \ }) #define EXPECT_TRAIT_FALSE(trait, ...) \ for_each_type>([](TypeWrapper) { \ STATIC_EXPECT_FALSE(trait); \ }) #define EXPECT_EQ_WITH_TRAIT(trait, ListA, ListB) \ for_each_type_zipped([](TypeWrapper, TypeWrapper) { \ STATIC_EXPECT_EQ(trait, B); \ }) #define EXPECT_VARIADIC_TRAIT_TRUE(trait, ...) \ static_assert(trait<__VA_ARGS__>) #define EXPECT_VARIADIC_TRAIT_FALSE(trait, ...) \ static_assert(!trait<__VA_ARGS__>) struct Empty { }; enum class Enummer : u8 { Dummmy, }; TEST_CASE(FundamentalTypeClassification) { EXPECT_TRAIT_TRUE(IsVoid, void); EXPECT_TRAIT_FALSE(IsVoid, int, Empty, std::nullptr_t); EXPECT_TRAIT_TRUE(IsNullPointer, std::nullptr_t); EXPECT_TRAIT_FALSE(IsNullPointer, void, int, Empty, decltype(0)); EXPECT_TRAIT_TRUE(IsFloatingPoint, float, double, long double); EXPECT_TRAIT_FALSE(IsFloatingPoint, int, Empty, std::nullptr_t, void); EXPECT_TRAIT_TRUE(IsArithmetic, float, double, long double, bool, size_t); EXPECT_TRAIT_TRUE(IsArithmetic, char, signed char, unsigned char, char8_t, char16_t, char32_t); EXPECT_TRAIT_TRUE(IsArithmetic, short, int, long, long long); EXPECT_TRAIT_TRUE(IsArithmetic, unsigned short, unsigned int, unsigned long, unsigned long long); EXPECT_TRAIT_FALSE(IsArithmetic, void, std::nullptr_t, Empty); EXPECT_TRAIT_TRUE(IsFundamental, void, std::nullptr_t); EXPECT_TRAIT_TRUE(IsFundamental, float, double, long double, bool, size_t); EXPECT_TRAIT_TRUE(IsFundamental, char, signed char, unsigned char, char8_t, char16_t, char32_t); EXPECT_TRAIT_TRUE(IsFundamental, short, int, long, long long); EXPECT_TRAIT_TRUE(IsFundamental, unsigned short, unsigned int, unsigned long, unsigned long long); EXPECT_TRAIT_FALSE(IsFundamental, Empty, int*, int&); EXPECT_TRAIT_FALSE(IsSigned, unsigned); EXPECT_TRAIT_FALSE(IsSigned, unsigned short); EXPECT_TRAIT_FALSE(IsSigned, unsigned char); EXPECT_TRAIT_FALSE(IsSigned, unsigned long); EXPECT_TRAIT_TRUE(IsSigned, int); EXPECT_TRAIT_TRUE(IsSigned, short); EXPECT_TRAIT_TRUE(IsSigned, long); EXPECT_TRAIT_TRUE(IsUnsigned, unsigned); EXPECT_TRAIT_TRUE(IsUnsigned, unsigned short); EXPECT_TRAIT_TRUE(IsUnsigned, unsigned char); EXPECT_TRAIT_TRUE(IsUnsigned, unsigned long); EXPECT_TRAIT_FALSE(IsUnsigned, int); EXPECT_TRAIT_FALSE(IsUnsigned, short); EXPECT_TRAIT_FALSE(IsUnsigned, long); EXPECT_TRAIT_TRUE(IsEnum, Enummer); EXPECT_TRAIT_FALSE(IsEnum, Empty); EXPECT_TRAIT_FALSE(IsEnum, int); EXPECT_TRAIT_FALSE(IsEnum, void); EXPECT_TRAIT_FALSE(IsEnum, std::nullptr_t); } TEST_CASE(AddConst) { // clang-format off using NoConstList = TypeList; using YesConstList = TypeList; // clang-format on EXPECT_EQ_WITH_TRAIT(AddConst, NoConstList, YesConstList); } TEST_CASE(UnderlyingType) { using Type = UnderlyingType; STATIC_EXPECT_EQ(Type, u8); } TEST_CASE(RemoveCVReference) { using TestTypeList = TypeList; using ResultTypeList = TypeList; EXPECT_EQ_WITH_TRAIT(RemoveCVReference, TestTypeList, ResultTypeList); } TEST_CASE(AddReference) { STATIC_EXPECT_EQ(AddLvalueReference, int&); STATIC_EXPECT_EQ(AddLvalueReference, int&); STATIC_EXPECT_EQ(AddLvalueReference, int&); STATIC_EXPECT_EQ(AddRvalueReference, int&&); STATIC_EXPECT_EQ(AddRvalueReference, int&); STATIC_EXPECT_EQ(AddRvalueReference, int&&); STATIC_EXPECT_EQ(AddLvalueReference, void); } TEST_CASE(IsConvertible) { struct A { }; struct B { B(A); }; struct C { A a; operator A() { return a; }; }; struct D { }; EXPECT_VARIADIC_TRAIT_TRUE(IsConvertible, A, B); EXPECT_VARIADIC_TRAIT_FALSE(IsConvertible, B, A); EXPECT_VARIADIC_TRAIT_TRUE(IsConvertible, C, A); EXPECT_VARIADIC_TRAIT_FALSE(IsConvertible, A, C); EXPECT_VARIADIC_TRAIT_FALSE(IsConvertible, D, A); EXPECT_VARIADIC_TRAIT_FALSE(IsConvertible, A, D); } TEST_CASE(IsAssignable) { EXPECT_VARIADIC_TRAIT_FALSE(IsAssignable, int, int); EXPECT_VARIADIC_TRAIT_TRUE(IsAssignable, int&, int); EXPECT_VARIADIC_TRAIT_FALSE(IsAssignable, int, void); struct A { }; EXPECT_TRAIT_TRUE(IsCopyAssignable, A); EXPECT_TRAIT_TRUE(IsTriviallyCopyAssignable, A); EXPECT_TRAIT_TRUE(IsMoveAssignable, A); EXPECT_TRAIT_TRUE(IsTriviallyMoveAssignable, A); struct B { B& operator=(const B&) { return *this; } B& operator=(B&&) { return *this; } }; EXPECT_TRAIT_TRUE(IsCopyAssignable, B); EXPECT_TRAIT_FALSE(IsTriviallyCopyAssignable, B); EXPECT_TRAIT_TRUE(IsMoveAssignable, B); EXPECT_TRAIT_FALSE(IsTriviallyMoveAssignable, B); struct C { C& operator=(const C&) = delete; C& operator=(C&&) = delete; }; EXPECT_TRAIT_FALSE(IsCopyAssignable, C); EXPECT_TRAIT_FALSE(IsTriviallyCopyAssignable, C); EXPECT_TRAIT_FALSE(IsMoveAssignable, C); EXPECT_TRAIT_FALSE(IsTriviallyMoveAssignable, C); } TEST_CASE(IsConstructible) { struct A { }; EXPECT_TRAIT_TRUE(IsCopyConstructible, A); EXPECT_TRAIT_TRUE(IsTriviallyCopyConstructible, A); EXPECT_TRAIT_TRUE(IsMoveConstructible, A); EXPECT_TRAIT_TRUE(IsTriviallyMoveConstructible, A); struct B { B(const B&) { } B(B&&) { } }; EXPECT_TRAIT_TRUE(IsCopyConstructible, B); EXPECT_TRAIT_FALSE(IsTriviallyCopyConstructible, B); EXPECT_TRAIT_TRUE(IsMoveConstructible, B); EXPECT_TRAIT_FALSE(IsTriviallyMoveConstructible, B); struct C { C(const C&) = delete; C(C&&) = delete; }; EXPECT_TRAIT_FALSE(IsCopyConstructible, C); EXPECT_TRAIT_FALSE(IsTriviallyCopyConstructible, C); EXPECT_TRAIT_FALSE(IsMoveConstructible, C); EXPECT_TRAIT_FALSE(IsTriviallyMoveConstructible, C); struct D { D(int); }; EXPECT_VARIADIC_TRAIT_TRUE(IsConstructible, D, int); EXPECT_VARIADIC_TRAIT_TRUE(IsConstructible, D, char); EXPECT_VARIADIC_TRAIT_FALSE(IsConstructible, D, const char*); EXPECT_VARIADIC_TRAIT_FALSE(IsConstructible, D, void); } TEST_CASE(IsDestructible) { struct A { }; EXPECT_TRAIT_TRUE(IsDestructible, A); EXPECT_TRAIT_TRUE(IsTriviallyDestructible, A); struct B { ~B() { } }; EXPECT_TRAIT_TRUE(IsDestructible, B); EXPECT_TRAIT_FALSE(IsTriviallyDestructible, B); struct C { ~C() = delete; }; EXPECT_TRAIT_FALSE(IsDestructible, C); EXPECT_TRAIT_FALSE(IsTriviallyDestructible, C); } TEST_CASE(CommonType) { using TCommon0 = CommonType; EXPECT_VARIADIC_TRAIT_TRUE(IsSame, TCommon0, float); using TCommon1 = CommonType; EXPECT_VARIADIC_TRAIT_TRUE(IsSame, TCommon1, int); struct Foo { }; using TCommon2 = CommonType; EXPECT_VARIADIC_TRAIT_TRUE(IsSame, TCommon2, Foo); struct Bar { operator Foo(); }; using TCommon3 = CommonType; EXPECT_VARIADIC_TRAIT_TRUE(IsSame, TCommon3, Foo); }