From c45848281c970e70598bc35c31ee9cd2fbc9239c Mon Sep 17 00:00:00 2001 From: jatin Date: Thu, 12 Oct 2023 23:46:19 -0700 Subject: [PATCH] Refactor and adding tests --- .../Types/chowdsp_TypeHasCheckers.h | 135 ++++++++++++++++++ .../chowdsp_core/Types/chowdsp_TypeTraits.h | 134 ----------------- modules/common/chowdsp_core/chowdsp_core.h | 1 + .../chowdsp_core_test/CMakeLists.txt | 1 + .../chowdsp_core_test/TypeCheckersTest.cpp | 70 +++++++++ 5 files changed, 207 insertions(+), 134 deletions(-) create mode 100644 modules/common/chowdsp_core/Types/chowdsp_TypeHasCheckers.h create mode 100644 tests/common_tests/chowdsp_core_test/TypeCheckersTest.cpp diff --git a/modules/common/chowdsp_core/Types/chowdsp_TypeHasCheckers.h b/modules/common/chowdsp_core/Types/chowdsp_TypeHasCheckers.h new file mode 100644 index 000000000..808f87c0a --- /dev/null +++ b/modules/common/chowdsp_core/Types/chowdsp_TypeHasCheckers.h @@ -0,0 +1,135 @@ +#pragma once + +/** + * Creates a constexpr bool that checks if a class has the given static method. + * + * Usage: + * @code {.cpp} + * CHOWDSP_CHECK_HAS_STATIC_METHOD(HasToString, toString, std::declval()) + * static_assert(HasToString, "MyClass must have a static toString(int) method!"); + * @endcode + */ +#define CHOWDSP_CHECK_HAS_STATIC_METHOD(Name, Method, ...) \ + template \ + class Test_##Name \ + { \ + using No = char; \ + using Yes = long; \ + static_assert (sizeof (No) != sizeof (Yes), "Yes and No have the same size on this platform, undefined behaviour will ensue!"); \ + \ + template \ + static Yes test (decltype (C::Method (__VA_ARGS__))*); \ + \ + template \ + static No test (...); \ + \ + public: \ + enum \ + { \ + value = sizeof (test<_T> (nullptr)) == sizeof (Yes) \ + }; \ + }; \ + template \ + static constexpr bool Name = Test_##Name<_T>::value; + +/** + * Creates a constexpr bool that checks if a class has the given non-static method. + * + * Usage: + * @code {.cpp} + * CHOWDSP_CHECK_HAS_METHOD(HasGetAtIndex, getAtIndex, std::declval()) + * static_assert(HasGetAtIndex, "MyClass must have getAtIndex(int) method!"); + * @endcode + */ +#define CHOWDSP_CHECK_HAS_METHOD(Name, Method, ...) \ + template \ + class Test_##Name \ + { \ + using No = char; \ + using Yes = long; \ + static_assert (sizeof (No) != sizeof (Yes), "Yes and No have the same size on this platform, undefined behaviour will ensue!"); \ + \ + template \ + static Yes test (decltype (std::declval().Method (__VA_ARGS__))*); \ + \ + template \ + static No test (...); \ + \ + public: \ + enum \ + { \ + value = sizeof (test<_T> (nullptr)) == sizeof (Yes) \ + }; \ + }; \ + template \ + static constexpr bool Name = Test_##Name<_T>::value; + +/** + * Creates a constexpr bool that checks if a class has the given static member variable. + * + * Usage: + * @code {.cpp} + * CHOWDSP_CHECK_HAS_STATIC_MEMBER(HasName, name) + * static_assert(HasName, "MyClass must have a static name member!"); + * @endcode + */ +#define CHOWDSP_CHECK_HAS_STATIC_MEMBER(Name, Member) \ + template \ + class Test_##Name \ + { \ + using No = char; \ + using Yes = long; \ + static_assert (sizeof (No) != sizeof (Yes), "Yes and No have the same size on this platform, undefined behaviour will ensue!"); \ + \ + template \ + static std::enable_if_t, No> test (decltype (C::Member)*); \ + \ + template \ + static std::enable_if_t, Yes> test (decltype (C::Member)*); \ + \ + template \ + static No test (...); \ + \ + public: \ + enum \ + { \ + value = sizeof (test<_T> (nullptr)) == sizeof (Yes) \ + }; \ + }; \ + template \ + static constexpr bool Name = Test_##Name<_T>::value; + +/** + * Creates a constexpr bool that checks if a class has the given non-static member variable. + * + * Usage: + * @code {.cpp} + * CHOWDSP_CHECK_HAS_MEMBER(HasName, name) + * static_assert(HasName, "MyClass must have `name` member variable!"); + * @endcode + */ +#define CHOWDSP_CHECK_HAS_MEMBER(Name, Member) \ + template \ + class Test_##Name \ + { \ + using No = char; \ + using Yes = long; \ + static_assert (sizeof (No) != sizeof (Yes), "Yes and No have the same size on this platform, undefined behaviour will ensue!"); \ + \ + template \ + static std::enable_if_t, Yes> test (decltype (std::declval().Member)*); \ + \ + template \ + static std::enable_if_t, No> test (decltype (std::declval().Member)*); \ + \ + template \ + static No test (...); \ + \ + public: \ + enum \ + { \ + value = sizeof (test<_T> (nullptr)) == sizeof (Yes) \ + }; \ + }; \ + template \ + static constexpr bool Name = Test_##Name<_T>::value; diff --git a/modules/common/chowdsp_core/Types/chowdsp_TypeTraits.h b/modules/common/chowdsp_core/Types/chowdsp_TypeTraits.h index 7c024e795..390601641 100644 --- a/modules/common/chowdsp_core/Types/chowdsp_TypeTraits.h +++ b/modules/common/chowdsp_core/Types/chowdsp_TypeTraits.h @@ -1,139 +1,5 @@ #pragma once -/** - * Creates a constexpr bool that checks if a class has the given static method. - * - * Usage: - * @code {.cpp} - * CHOWDSP_CHECK_HAS_STATIC_METHOD(HasToString, toString) - * static_assert(HasToString, "MyClass must have a static toString method!"); - * @endcode - */ -#define CHOWDSP_CHECK_HAS_STATIC_METHOD(Name, Method) \ - template \ - class Test_##Name \ - { \ - using No = char; \ - using Yes = long; \ - static_assert (sizeof (No) != sizeof (Yes), "Yes and No have the same size on this platform, undefined behaviour will ensue!"); \ - \ - template \ - static Yes test (decltype (&C::Method)); \ - \ - template \ - static No test (...); \ - \ - public: \ - enum \ - { \ - value = sizeof (test<_T> (nullptr)) == sizeof (Yes) \ - }; \ - }; \ - template \ - static constexpr bool Name = Test_##Name<_T>::value; - -/** - * Creates a constexpr bool that checks if a class has the given non-static method. - * - * Usage: - * @code {.cpp} - * CHOWDSP_CHECK_HAS_METHOD(HasGetAtIndex, getAtIndex, int{}) - * static_assert(HasGetAtIndex, "MyClass must have getAtIndex(int) method!"); - * @endcode - */ -#define CHOWDSP_CHECK_HAS_METHOD(Name, Method, ...) \ - template \ - class Test_##Name \ - { \ - using No = char; \ - using Yes = long; \ - static_assert (sizeof (No) != sizeof (Yes), "Yes and No have the same size on this platform, undefined behaviour will ensue!"); \ - \ - template \ - static Yes test (decltype (std::declval().Method (__VA_ARGS__))*); \ - \ - template \ - static No test (...); \ - \ - public: \ - enum \ - { \ - value = sizeof (test<_T> (nullptr)) == sizeof (Yes) \ - }; \ - }; \ - template \ - static constexpr bool Name = Test_##Name<_T>::value; - -/** - * Creates a constexpr bool that checks if a class has the given static member variable. - * - * Usage: - * @code {.cpp} - * CHOWDSP_CHECK_HAS_STATIC_MEMBER(HasName, name) - * static_assert(HasName, "MyClass must have a static name method!"); - * @endcode - */ -#define CHOWDSP_CHECK_HAS_STATIC_MEMBER(Name, Member) \ - template \ - class Test_##Name \ - { \ - using No = char; \ - using Yes = long; \ - static_assert (sizeof (No) != sizeof (Yes), "Yes and No have the same size on this platform, undefined behaviour will ensue!"); \ - \ - template \ - static std::enable_if_t, No> test (decltype (C::Member)*); \ - \ - template \ - static std::enable_if_t, Yes> test (decltype (C::Member)*); \ - \ - template \ - static No test (...); \ - \ - public: \ - enum \ - { \ - value = sizeof (test<_T> (nullptr)) == sizeof (Yes) \ - }; \ - }; \ - template \ - static constexpr bool Name = Test_##Name<_T>::value; - -/** - * Creates a constexpr bool that checks if a class has the given non-static member variable. - * - * Usage: - * @code {.cpp} - * CHOWDSP_CHECK_HAS_MEMBER(HasName, name) - * static_assert(HasName, "MyClass must have `name` member variable!"); - * @endcode - */ -#define CHOWDSP_CHECK_HAS_MEMBER(Name, Member) \ - template \ - class Test_##Name \ - { \ - using No = char; \ - using Yes = long; \ - static_assert (sizeof (No) != sizeof (Yes), "Yes and No have the same size on this platform, undefined behaviour will ensue!"); \ - \ - template \ - static std::enable_if_t, Yes> test (decltype (std::declval().Member)*); \ - \ - template \ - static std::enable_if_t, No> test (decltype (std::declval().Member)*); \ - \ - template \ - static No test (...); \ - \ - public: \ - enum \ - { \ - value = sizeof (test<_T> (nullptr)) == sizeof (Yes) \ - }; \ - }; \ - template \ - static constexpr bool Name = Test_##Name<_T>::value; - namespace chowdsp { /** Helpers for evaluating type traits */ diff --git a/modules/common/chowdsp_core/chowdsp_core.h b/modules/common/chowdsp_core/chowdsp_core.h index 105ebf608..346977fa3 100644 --- a/modules/common/chowdsp_core/chowdsp_core.h +++ b/modules/common/chowdsp_core/chowdsp_core.h @@ -98,4 +98,5 @@ namespace experimental #include "Functional/chowdsp_Bindings.h" #include "Functional/chowdsp_EndOfScopeAction.h" #include "Memory/chowdsp_MemoryAliasing.h" +#include "Types/chowdsp_TypeHasCheckers.h" #include "Types/chowdsp_TypeTraits.h" diff --git a/tests/common_tests/chowdsp_core_test/CMakeLists.txt b/tests/common_tests/chowdsp_core_test/CMakeLists.txt index a2c73a960..114e767b5 100644 --- a/tests/common_tests/chowdsp_core_test/CMakeLists.txt +++ b/tests/common_tests/chowdsp_core_test/CMakeLists.txt @@ -5,6 +5,7 @@ target_sources(chowdsp_core_test AtomicHelpersTest.cpp MemoryAliasingTest.cpp TypesListTest.cpp + TypeCheckersTest.cpp TypeTraitsTest.cpp BindingsTest.cpp ScopedValueTest.cpp diff --git a/tests/common_tests/chowdsp_core_test/TypeCheckersTest.cpp b/tests/common_tests/chowdsp_core_test/TypeCheckersTest.cpp new file mode 100644 index 000000000..c67c1678a --- /dev/null +++ b/tests/common_tests/chowdsp_core_test/TypeCheckersTest.cpp @@ -0,0 +1,70 @@ +#include +#include + +CHOWDSP_CHECK_HAS_MEMBER (HasName, name) +CHOWDSP_CHECK_HAS_STATIC_MEMBER (HasStaticName, name) +struct Type_With_No_Name +{ +}; +struct Type_With_Name +{ + std::string name; +}; +struct Type_With_Name_And_Ctor +{ + Type_With_Name_And_Ctor (int, bool) {} + std::string name; +}; +struct Type_With_Static_Name +{ + static std::string name; +}; + +CHOWDSP_CHECK_HAS_METHOD (HasGetName, getName, std::declval()) +CHOWDSP_CHECK_HAS_STATIC_METHOD (HasStaticGetName, getName, std::declval()) +struct Type_With_Get_Name +{ + std::string getName (Type_With_Name_And_Ctor&) { return ""; } +}; +struct Type_With_Get_Name_And_Ctor +{ + Type_With_Get_Name_And_Ctor (int, bool) {} + std::string getName (Type_With_Name_And_Ctor&) { return ""; } +}; +struct Type_With_Static_Get_Name +{ + static std::string getName (Type_With_Name_And_Ctor&) { return ""; } +}; + +TEST_CASE ("Type Checkers Test", "[common][types]") +{ + SECTION ("Has Member") + { + STATIC_REQUIRE (HasName == false); + STATIC_REQUIRE (HasName == true); + STATIC_REQUIRE (HasName == true); + STATIC_REQUIRE (HasName == false); + } + + SECTION ("Has Static Member") + { + STATIC_REQUIRE (HasStaticName == false); + STATIC_REQUIRE (HasStaticName == false); + STATIC_REQUIRE (HasStaticName == true); + } + + SECTION ("Has Method") + { + STATIC_REQUIRE (HasGetName == false); + STATIC_REQUIRE (HasGetName == true); + STATIC_REQUIRE (HasGetName == true); + } + + SECTION ("Has Static Method") + { + STATIC_REQUIRE (HasStaticGetName == false); + STATIC_REQUIRE (HasStaticGetName == false); + STATIC_REQUIRE (HasStaticGetName == false); + STATIC_REQUIRE (HasStaticGetName == true); + } +}