diff --git a/include/etl/function_traits.h b/include/etl/function_traits.h new file mode 100644 index 00000000..5d30d684 --- /dev/null +++ b/include/etl/function_traits.h @@ -0,0 +1,136 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_FUNCTION_TRAITS_INCLUDED +#define ETL_FUNCTION_TRAITS_INCLUDED + +#include "platform.h" +#include "type_list.h" +#include "type_traits.h" + +#if ETL_USING_CPP11 +namespace etl +{ + //*************************************************************************** + /// A template to extract the function type traits. + //*************************************************************************** + template + struct function_traits; + + //*************************************************************************** + /// Specialisation for function pointers + //*************************************************************************** + template + struct function_traits + { + using function_type = TReturn(TArgs...); ///< The signature of the function. + using return_type = TReturn; ///< The return type. + using object_type = void; ///< The object type, if a member function. + using argument_types = etl::type_list; ///< An etl::type_list containing the function argument types. + + static constexpr bool is_function = true; ///< true if the type is a free, static or global function, otherwise false. + static constexpr bool is_member_function = false; ///< true if the type is a member function, otherwise false. + static constexpr bool is_const = false; ///< true if the type is a const member function, otherwise false. + static constexpr size_t argument_count = sizeof...(TArgs); ///< The number of arguments that the function takes. + }; + + template + constexpr bool function_traits::is_function; + + template + constexpr bool function_traits::is_member_function; + + template + constexpr bool function_traits::is_const; + + template + constexpr size_t function_traits::argument_count; + + //*************************************************************************** + /// Specialisation for member function pointers + //*************************************************************************** + template + struct function_traits + { + using function_type = TReturn(TArgs...); ///< The signature of the function. + using return_type = TReturn; ///< The return type. + using object_type = TObject; ///< The object type, if a member function. + using argument_types = etl::type_list; ///< An etl::type_list containing the function argument types. + + static constexpr bool is_function = false; ///< true if the type is a free, static or global function, otherwise false. + static constexpr bool is_member_function = true; ///< true if the type is a member function, otherwise false. + static constexpr bool is_const = false; ///< true if the type is a const member function, otherwise false. + static constexpr size_t argument_count = sizeof...(TArgs); ///< The number of arguments that the function takes. + }; + + template + constexpr bool function_traits::is_function; + + template + constexpr bool function_traits::is_member_function; + + template + constexpr bool function_traits::is_const; + + template + constexpr size_t function_traits::argument_count; + + //*************************************************************************** + /// Specialisation for const member function pointers + //*************************************************************************** + template + struct function_traits + { + using function_type = TReturn(TArgs...); ///< The signature of the function. + using return_type = TReturn; ///< The return type. + using object_type = TObject; ///< The object type, if a member function. + using argument_types = etl::type_list; ///< An etl::type_list containing the function argument types. + + static constexpr bool is_function = false; ///< true if the type is a free, static or global function, otherwise false. + static constexpr bool is_member_function = true; ///< true if the type is a member function, otherwise false. + static constexpr bool is_const = true; ///< true if the type is a const member function, otherwise false. + static constexpr size_t argument_count = sizeof...(TArgs); ///< The number of arguments that the function takes. + }; + + template + constexpr bool function_traits::is_function; + + template + constexpr bool function_traits::is_member_function; + + template + constexpr bool function_traits::is_const; + + template + constexpr size_t function_traits::argument_count; +} +#endif + +#endif diff --git a/include/etl/nth_type.h b/include/etl/nth_type.h index 5bc1e836..ca353458 100644 --- a/include/etl/nth_type.h +++ b/include/etl/nth_type.h @@ -63,7 +63,7 @@ namespace etl }; //*************************************************************************** - /// Finds the 0thth type in a variadic type parameter. + /// Finds the 0th type in a variadic type parameter. //*************************************************************************** template struct nth_type diff --git a/include/etl/private/delegate_cpp11.h b/include/etl/private/delegate_cpp11.h index e1f7c396..0bb8025e 100644 --- a/include/etl/private/delegate_cpp11.h +++ b/include/etl/private/delegate_cpp11.h @@ -52,6 +52,7 @@ Original publication: https://www.codeproject.com/Articles/1170503/The-Impossibl #include "../error_handler.h" #include "../exception.h" #include "../type_traits.h" +#include "../function_traits.h" #include "../utility.h" #include "../optional.h" @@ -659,57 +660,6 @@ namespace etl }; #if ETL_USING_CPP17 - namespace private_delegate - { - //*************************************************************************** - /// A template to extract the function type traits. - //*************************************************************************** - template - struct function_traits; - - //*************************************************************************** - /// Specialisation for function pointers - //*************************************************************************** - template - struct function_traits - { - using function_type = TReturn(TArgs...); - - enum : bool - { - is_const = false - }; - }; - - //*************************************************************************** - /// Specialisation for member function pointers - //*************************************************************************** - template - struct function_traits - { - using function_type = TReturn(TArgs...); - - enum : bool - { - is_const = false - }; - }; - - //*************************************************************************** - /// Specialisation for const member function pointers - //*************************************************************************** - template - struct function_traits - { - using function_type = TReturn(TArgs...); - - enum : bool - { - is_const = true - }; - }; - } - //************************************************************************* /// Make a delegate from a free function. //************************************************************************* @@ -717,7 +667,7 @@ namespace etl ETL_NODISCARD constexpr auto make_delegate() ETL_NOEXCEPT { - using function_type = typename etl::private_delegate::function_traits::function_type; + using function_type = typename etl::function_traits::function_type; return etl::delegate::template create(); } @@ -729,7 +679,7 @@ namespace etl ETL_NODISCARD constexpr auto make_delegate(TLambda& instance) ETL_NOEXCEPT { - using function_type = typename etl::private_delegate::function_traits::function_type; + using function_type = typename etl::function_traits::function_type; return etl::delegate(instance); } @@ -741,7 +691,7 @@ namespace etl ETL_NODISCARD constexpr auto make_delegate() ETL_NOEXCEPT { - using function_type = typename etl::private_delegate::function_traits::function_type; + using function_type = typename etl::function_traits::function_type; return etl::delegate::template create(); } @@ -749,11 +699,11 @@ namespace etl //************************************************************************* /// Make a delegate from a member function at compile time. //************************************************************************* - template ::is_const>> + template ::is_const>> ETL_NODISCARD constexpr auto make_delegate() ETL_NOEXCEPT { - using function_type = typename etl::private_delegate::function_traits::function_type; + using function_type = typename etl::function_traits::function_type; return etl::delegate::template create(); } @@ -761,11 +711,11 @@ namespace etl //************************************************************************* /// Make a delegate from a const member function at compile time. //************************************************************************* - template ::is_const>> + template ::is_const>> ETL_NODISCARD constexpr auto make_delegate() ETL_NOEXCEPT { - using function_type = typename etl::private_delegate::function_traits::function_type; + using function_type = typename etl::function_traits::function_type; return etl::delegate::template create(); } @@ -777,7 +727,7 @@ namespace etl ETL_NODISCARD constexpr auto make_delegate(T& instance) ETL_NOEXCEPT { - using function_type = typename etl::private_delegate::function_traits::function_type; + using function_type = typename etl::function_traits::function_type; return etl::delegate::template create(instance); } @@ -789,7 +739,7 @@ namespace etl ETL_NODISCARD constexpr auto make_delegate(const T& instance) ETL_NOEXCEPT { - using function_type = typename etl::private_delegate::function_traits::function_type; + using function_type = typename etl::function_traits::function_type; return etl::delegate::template create(instance); } diff --git a/include/etl/type_list.h b/include/etl/type_list.h new file mode 100644 index 00000000..533ae761 --- /dev/null +++ b/include/etl/type_list.h @@ -0,0 +1,186 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_TYPE_LIST_INCLUDED +#define ETL_TYPE_LIST_INCLUDED + +#include "platform.h" +#include "nth_type.h" +#include "static_assert.h" +#include "type_traits.h" +#include "utility.h" + +#if ETL_USING_CPP11 +namespace etl +{ + //*************************************************************************** + /// Type list forward declaration. + //*************************************************************************** + template + struct type_list; + + //*************************************************************************** + /// The empty type list. + //*************************************************************************** + template <> + struct type_list<> + { + static constexpr size_t size = 0U; + + using index_sequence_type = etl::make_index_sequence<0>; ///< The index_sequence type for this type_list. + + private: + + type_list() ETL_DELETE; + type_list(const type_list&) ETL_DELETE; + type_list& operator =(const type_list&) ETL_DELETE; + }; + + //*************************************************************************** + /// Recursive type list implementation for multiple types. + //*************************************************************************** + template + struct type_list : type_list + { + using type = THead; + + static constexpr size_t size = sizeof...(TTail) + 1U; + + using index_sequence_type = etl::make_index_sequence; ///< The index_sequence type for this type_list. + + private: + + type_list() ETL_DELETE; + type_list(const type_list&) ETL_DELETE; + type_list& operator =(const type_list&) ETL_DELETE; + }; + + //*************************************************************************** + /// Type list implementation for one type. + //*************************************************************************** + template + struct type_list : type_list<> + { + using type = THead; + + static constexpr size_t size = 1U; + + using index_sequence_type = etl::make_index_sequence<1>; ///< The index_sequence type for this type_list. + + private: + + type_list() ETL_DELETE; + type_list(const type_list&) ETL_DELETE; + type_list& operator =(const type_list&) ETL_DELETE; + }; + + //*************************************************************************** + /// Specialisation of etl::nth_type for etl::type_list + //*************************************************************************** + template + struct nth_type> + { + ETL_STATIC_ASSERT(N <= sizeof...(TTail), "etl::nth_type out of range for etl::type_list"); + + using type = typename nth_type>::type; + }; + + //*************************************************************************** + /// Specialisation of etl::nth_type for etl::type_list with index of 0 + //*************************************************************************** + template + struct nth_type<0, type_list> + { + using type = THead; + }; + + //*************************************************************************** + /// Specialisation of etl::nth_type for empty etl::type_list + //*************************************************************************** + template + struct nth_type> + { + }; + + //*************************************************************************** + /// Declares a new type_list by selecting types from a given type_list, according to an index sequence. + //*************************************************************************** + template + struct type_list_select + { + using type = type_list...>; + }; + + template + using type_list_select_t = typename type_list_select::type; + + //*************************************************************************** + /// Type list size. + //*************************************************************************** + template + struct type_list_size; + + template + struct type_list_size> : public etl::integral_constant + { + }; + +#if ETL_USING_CPP17 + template + inline constexpr size_t type_list_size_v = type_list_size>::value; +#endif + + //*************************************************************************** + /// Concatenates two or more type_lists. + //*************************************************************************** + template + struct type_list_cat; + + //*************************************************************************** + /// Concatenates two or more type_lists. + /// Specialisation for a single type_list (base case) + //*************************************************************************** + template + struct type_list_cat + { + using type = TypeList; + }; + + //*************************************************************************** + /// Concatenates two or more type_lists. + /// Specialisation for two or more type_lists + //*************************************************************************** + template + struct type_list_cat, etl::type_list, TTail...> + { + using type = typename type_list_cat, TTail...>::type; + }; +} +#endif + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9503098d..5a8181cc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -143,6 +143,7 @@ add_executable(etl_tests test_fsm.cpp test_function.cpp test_functional.cpp + test_function_traits.cpp test_gamma.cpp test_hash.cpp test_hfsm.cpp diff --git a/test/syntax_check/CMakeLists.txt b/test/syntax_check/CMakeLists.txt index b82ee036..84cce67b 100644 --- a/test/syntax_check/CMakeLists.txt +++ b/test/syntax_check/CMakeLists.txt @@ -178,6 +178,7 @@ target_sources(tests PRIVATE fsm.h.t.cpp function.h.t.cpp functional.h.t.cpp + function_traits.h.t.cpp gamma.h.t.cpp gcd.h.t.cpp generic_pool.h.t.cpp diff --git a/test/syntax_check/function_traits.h.t.cpp b/test/syntax_check/function_traits.h.t.cpp new file mode 100644 index 00000000..955b6be0 --- /dev/null +++ b/test/syntax_check/function_traits.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/test_function_traits.cpp b/test/test_function_traits.cpp new file mode 100644 index 00000000..3e065f58 --- /dev/null +++ b/test/test_function_traits.cpp @@ -0,0 +1,211 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2024 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include + +#include "etl/function_traits.h" +#include "etl/type_list.h" + +namespace +{ + //***************************************************************************** + // The free function taking no parameters. + //***************************************************************************** + void free_void() + { + } + + //***************************************************************************** + // The free function taking an int parameter. + //***************************************************************************** + int free_int(int i, int j) + { + return i + j; + } + + //***************************************************************************** + // The test class with member functions. + //***************************************************************************** + class Object + { + public: + + //******************************************* + // void + void member_void() + { + } + + void member_void_const() const + { + } + + //******************************************* + // int + int member_int(int i, int j) + { + return i + j; + } + + int member_int_const(int i, int j) const + { + return i + j; + } + + //******************************************* + // static + static void member_static(int j) + { + (void)j; + } + }; +} + +namespace +{ + SUITE(test_function_traits) + { + //************************************************************************* + TEST(test_free_function_free_void) + { + free_void(); // Keep clang happy + + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_TRUE(traits::is_function); + CHECK_FALSE(traits::is_member_function); + CHECK_FALSE(traits::is_const); + CHECK_EQUAL(0, traits::argument_count); + } + + //************************************************************************* + TEST(test_free_function_free_int) + { + free_int(1, 2); // Keep clang happy + + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_TRUE(traits::is_function); + CHECK_FALSE(traits::is_member_function); + CHECK_FALSE(traits::is_const); + CHECK_EQUAL(2 , traits::argument_count); + } + + //************************************************************************* + TEST(test_member_function_void) + { + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_const); + CHECK_EQUAL(0, traits::argument_count); + } + + //************************************************************************* + TEST(test_member_function_void_const) + { + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_TRUE(traits::is_const); + CHECK_EQUAL(0, traits::argument_count); + } + + //************************************************************************* + TEST(test_member_function_int) + { + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_const); + CHECK_EQUAL(2, traits::argument_count); + } + + //************************************************************************* + TEST(test_member_function_int_const) + { + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_TRUE(traits::is_const); + CHECK_EQUAL(2, traits::argument_count); + } + + //************************************************************************* + TEST(test_member_function_static) + { + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_TRUE(traits::is_function); + CHECK_FALSE(traits::is_member_function); + CHECK_FALSE(traits::is_const); + CHECK_EQUAL(1, traits::argument_count); + } + }; +} diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 28f9f338..0ed83920 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3084,6 +3084,7 @@ + @@ -3248,6 +3249,7 @@ + @@ -5582,6 +5584,21 @@ true true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true true @@ -8079,6 +8096,7 @@ +