diff --git a/include/etl/type_list.h b/include/etl/type_list.h index 533ae761..556787ab 100644 --- a/include/etl/type_list.h +++ b/include/etl/type_list.h @@ -30,7 +30,10 @@ SOFTWARE. #define ETL_TYPE_LIST_INCLUDED #include "platform.h" + +#include "algorithm.h" #include "nth_type.h" +#include "integral_limits.h" #include "static_assert.h" #include "type_traits.h" #include "utility.h" @@ -38,6 +41,9 @@ SOFTWARE. #if ETL_USING_CPP11 namespace etl { + + static ETL_CONSTEXPR size_t type_list_npos = etl::integral_limits::max; + //*************************************************************************** /// Type list forward declaration. //*************************************************************************** @@ -61,6 +67,18 @@ namespace etl type_list& operator =(const type_list&) ETL_DELETE; }; + namespace private_type_list + { + + // helper to solve the issue that recursed-rest can't be put directly in type_list::tail definition + template + struct recursion_helper + { + using type = type_list; + }; + + } + //*************************************************************************** /// Recursive type list implementation for multiple types. //*************************************************************************** @@ -68,6 +86,7 @@ namespace etl struct type_list : type_list { using type = THead; + using tail = typename private_type_list::recursion_helper::type; static constexpr size_t size = sizeof...(TTail) + 1U; @@ -87,6 +106,7 @@ namespace etl struct type_list : type_list<> { using type = THead; + using tail = typename private_type_list::recursion_helper<>::type; static constexpr size_t size = 1U; @@ -180,6 +200,77 @@ namespace etl { using type = typename type_list_cat, TTail...>::type; }; + + template + struct type_list_contains + : public etl::integral_constant::value ? true : type_list_contains::value> + { + }; + + template + struct type_list_contains, T> + : public etl::integral_constant + { + }; + +#if ETL_USING_CPP17 + template + inline constexpr bool type_list_contains_v = etl::type_list_contains::value; +#endif + + template + struct type_list_index_of + : public etl::integral_constant::value ? 0 : + (type_list_index_of::value == type_list_npos ? + type_list_npos : type_list_index_of::value + 1)> + { + }; + + template + struct type_list_index_of, T> + : public etl::integral_constant + { + }; + +#if ETL_USING_CPP17 + template + inline constexpr size_t type_list_index_of_v = etl::type_list_index_of::value; +#endif + + template + struct type_list_max_sizeof_type + : public etl::integral_constant::value)> + { + }; + + template<> + struct type_list_max_sizeof_type> + : public etl::integral_constant + { + }; + +#if ETL_USING_CPP17 + template + inline constexpr size_t type_list_max_sizeof_type_v = etl::type_list_max_sizeof_type::value; +#endif + + template + struct type_list_max_alignment + : public etl::integral_constant::value, + type_list_max_alignment::value)> + { + }; + + template<> + struct type_list_max_alignment> + : public etl::integral_constant + { + }; + +#if ETL_USING_CPP17 + template + inline constexpr size_t type_list_max_alignment_v = etl::type_list_max_alignment::value; +#endif } #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bcc8a0da..d2641ab5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -286,6 +286,7 @@ add_executable(etl_tests test_to_u8string.cpp test_to_wstring.cpp test_type_def.cpp + test_type_list.cpp test_type_lookup.cpp test_type_select.cpp test_type_traits.cpp diff --git a/test/test_type_list.cpp b/test/test_type_list.cpp new file mode 100644 index 00000000..44f197f8 --- /dev/null +++ b/test/test_type_list.cpp @@ -0,0 +1,172 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 BMW AG + +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 "etl/type_list.h" + +#include + +namespace +{ +#if ETL_USING_CPP11 + SUITE(test_type_list) + { + //************************************************************************* + TEST(test_nth_type) + { + typedef etl::type_list t1; + + CHECK_TRUE((std::is_same::type, char>::value)); + CHECK_TRUE((std::is_same::type, int>::value)); + CHECK_TRUE((std::is_same::type, uint32_t>::value)); + } + + //************************************************************************* + TEST(test_type_list_select) + { + typedef etl::type_list t1; + typedef etl::type_list t2; + + CHECK_TRUE((std::is_same::type, t2>::value)); + } + + //************************************************************************* + TEST(test_type_list_size) + { + typedef etl::type_list t1; + typedef etl::type_list t2; + + CHECK_EQUAL(etl::type_list_size::value, 3); + CHECK_EQUAL(etl::type_list_size::value, 2); + } + + //************************************************************************* + TEST(test_type_list_cat) + { + typedef etl::type_list t1; + typedef etl::type_list t2; + + typedef etl::type_list t_cat1; + typedef etl::type_list t_cat2; + + CHECK_TRUE((std::is_same::type, t_cat1>::value)); + CHECK_FALSE((std::is_same::type, t_cat2>::value)); + } + + //************************************************************************* + TEST(test_type_list_contains) + { + typedef etl::type_list t1; + typedef etl::type_list t2; + typedef etl::type_list t3; + typedef etl::type_list<> t4; + + CHECK_TRUE((etl::type_list_contains::value)); + CHECK_FALSE((etl::type_list_contains::value)); + CHECK_FALSE((etl::type_list_contains::value)); + CHECK_TRUE((etl::type_list_contains::value)); + CHECK_TRUE((etl::type_list_contains::value)); + CHECK_FALSE((etl::type_list_contains::value)); + CHECK_FALSE((etl::type_list_contains::value)); + +#if ETL_USING_CPP17 + CHECK_TRUE((etl::type_list_contains_v)); + CHECK_FALSE((etl::type_list_contains_v)); + CHECK_FALSE((etl::type_list_contains_v)); + CHECK_TRUE((etl::type_list_contains_v)); + CHECK_TRUE((etl::type_list_contains_v)); + CHECK_FALSE((etl::type_list_contains_v)); + CHECK_FALSE((etl::type_list_contains_v)); +#endif + } + + //************************************************************************* + TEST(test_type_list_index_of) + { + typedef etl::type_list t1; + typedef etl::type_list<> t2; + + CHECK_EQUAL((etl::type_list_index_of::value), 0); + CHECK_EQUAL((etl::type_list_index_of::value), 1); + CHECK_EQUAL((etl::type_list_index_of::value), 2); + CHECK_EQUAL((etl::type_list_index_of::value), etl::type_list_npos); + +#if ETL_USING_CPP17 + CHECK_EQUAL((etl::type_list_index_of_v), 0); + CHECK_EQUAL((etl::type_list_index_of_v), 1); + CHECK_EQUAL((etl::type_list_index_of_v), 2); + CHECK_EQUAL((etl::type_list_index_of_v), etl::type_list_npos); +#endif + } + + //************************************************************************* + TEST(test_type_list_max_sizeof_type) + { + typedef etl::type_list t1; + typedef etl::type_list t2; + typedef etl::type_list t3; + typedef etl::type_list<> t4; + + CHECK_EQUAL(etl::type_list_max_sizeof_type::value, 4); + CHECK_EQUAL(etl::type_list_max_sizeof_type::value, 2); + CHECK_EQUAL(etl::type_list_max_sizeof_type::value, 4); + CHECK_EQUAL(etl::type_list_max_sizeof_type::value, 0); + +#if ETL_USING_CPP17 + CHECK_EQUAL((etl::type_list_max_sizeof_type_v), 4); + CHECK_EQUAL((etl::type_list_max_sizeof_type_v), 2); + CHECK_EQUAL((etl::type_list_max_sizeof_type_v), 4); + CHECK_EQUAL((etl::type_list_max_sizeof_type_v), 0); +#endif + } + + //************************************************************************* + TEST(test_type_list_max_alignment) + { + typedef etl::type_list t1; + typedef etl::type_list t2; + typedef etl::type_list t3; + typedef etl::type_list<> t4; + + CHECK_EQUAL(etl::type_list_max_alignment::value, std::alignment_of::value); + CHECK_EQUAL(etl::type_list_max_alignment::value, std::alignment_of::value); + CHECK_EQUAL(etl::type_list_max_alignment::value, std::alignment_of::value); + CHECK_EQUAL(etl::type_list_max_alignment::value, 1); + +#if ETL_USING_CPP17 + CHECK_EQUAL((etl::type_list_max_alignment_v), std::alignment_of::value); + CHECK_EQUAL((etl::type_list_max_alignment_v), std::alignment_of::value); + CHECK_EQUAL((etl::type_list_max_alignment_v), std::alignment_of::value); + CHECK_EQUAL((etl::type_list_max_alignment_v), 1); +#endif + } + + }; +#endif +}