Refactored and simplified some features of etl::type_list

Removed nth_type specialisation for etl::type_list
This commit is contained in:
John Wellbelove 2025-03-16 19:08:55 +00:00
parent 495ea2b943
commit 03ca499e5e
5 changed files with 140 additions and 146 deletions

View File

@ -32,11 +32,12 @@ SOFTWARE.
#include "platform.h"
#include "algorithm.h"
#include "nth_type.h"
#include "index_of_type.h"
#include "integral_limits.h"
#include "static_assert.h"
#include "type_traits.h"
#include "utility.h"
#include "largest.h"
#if ETL_USING_CPP11
namespace etl
@ -85,7 +86,7 @@ namespace etl
template <typename THead, typename... TTail>
struct type_list<THead, TTail...> : type_list<TTail...>
{
using type = THead;
using head = THead;
using tail = typename private_type_list::recursion_helper<TTail...>::type;
static constexpr size_t size = sizeof...(TTail) + 1U;
@ -105,7 +106,7 @@ namespace etl
template <typename THead>
struct type_list<THead> : type_list<>
{
using type = THead;
using head = THead;
using tail = typename private_type_list::recursion_helper<>::type;
static constexpr size_t size = 1U;
@ -119,50 +120,10 @@ namespace etl
type_list& operator =(const type_list&) ETL_DELETE;
};
//***************************************************************************
/// Specialisation of etl::nth_type for etl::type_list
//***************************************************************************
template <size_t N, typename THead, typename... TTail>
struct nth_type<N, type_list<THead, TTail...>>
{
ETL_STATIC_ASSERT(N <= sizeof...(TTail), "etl::nth_type out of range for etl::type_list");
using type = typename nth_type<N - 1, type_list<TTail...>>::type;
};
//***************************************************************************
/// Specialisation of etl::nth_type for etl::type_list with index of 0
//***************************************************************************
template <typename THead, typename... TTail>
struct nth_type<0, type_list<THead, TTail...>>
{
using type = THead;
};
//***************************************************************************
/// Specialisation of etl::nth_type for empty etl::type_list
//***************************************************************************
template <size_t N>
struct nth_type<N, type_list<>>
{
};
//***************************************************************************
/// Declares a new type_list by selecting types from a given type_list, according to an index sequence.
//***************************************************************************
template <typename TTypeList, size_t... Indices>
struct type_list_select
{
using type = type_list<nth_type_t<Indices, TTypeList>...>;
};
template <typename TTypeList, size_t... Indices>
using type_list_select_t = typename type_list_select<TTypeList, Indices...>::type;
//***************************************************************************
/// Type list size.
//***************************************************************************
template <typename... TTypes>
template <typename TTypes>
struct type_list_size;
template <typename... TTypes>
@ -176,37 +137,60 @@ namespace etl
#endif
//***************************************************************************
/// Concatenates two or more type_lists.
/// Defines type as the type found at Index in the type_list.
/// Static asserts if Index is out of range.
//***************************************************************************
template <typename... TypeLists>
struct type_list_cat;
//***************************************************************************
/// Concatenates two or more type_lists.
/// Specialisation for a single type_list (base case)
//***************************************************************************
template <typename TypeList>
struct type_list_cat<TypeList>
template <typename TTypeList, size_t Index>
struct type_list_type_at_index
{
using type = TypeList;
ETL_STATIC_ASSERT(Index < type_list_size<TTypeList>::value, "etl::type_list_type_at_index out of range");
ETL_STATIC_ASSERT((etl::is_base_of<etl::type_list<>, TTypeList>::value), "TTypeList must be an etl::type_list");
using type = typename type_list_type_at_index<typename TTypeList::tail, Index - 1>::type;
};
//***************************************************************************
/// Concatenates two or more type_lists.
/// Specialisation for two or more type_lists
//***************************************************************************
template <typename... TTypes1, typename... TTypes2, typename... TTail>
struct type_list_cat<etl::type_list<TTypes1...>, etl::type_list<TTypes2...>, TTail...>
template <typename TTypeList>
struct type_list_type_at_index<TTypeList, 0>
{
using type = typename type_list_cat<etl::type_list<TTypes1..., TTypes2...>, TTail...>::type;
using type = typename TTypeList::head;
};
template <typename TTypeList, size_t Index>
using type_list_type_at_index_t = typename type_list_type_at_index<TTypeList, Index>::type;
//***************************************************************************
/// Defines an integral constant that is the index of the specified type in the type_list.
/// If the type is not in the type_list, then defined as etl::type_list_npos.
//***************************************************************************
template <typename TTypeList, typename T>
struct type_list_index_of_type
: public etl::integral_constant<size_t, etl::is_same<typename TTypeList::head, T>::value ? 0 :
(type_list_index_of_type<typename TTypeList::tail, T>::value == etl::type_list_npos ? etl::type_list_npos :
type_list_index_of_type<typename TTypeList::tail, T>::value + 1)>
{
ETL_STATIC_ASSERT((etl::is_base_of<etl::type_list<>, TTypeList>::value), "TTypeList must be an etl::type_list");
};
template <typename T>
struct type_list_index_of_type<type_list<>, T>
: public etl::integral_constant<size_t, etl::type_list_npos>
{
};
#if ETL_USING_CPP17
template <typename TTypeList, typename T>
inline constexpr size_t type_list_index_of_v = etl::type_list_index_of_type<TTypeList, T>::value;
#endif
//***************************************************************************
/// Defines a bool constant that is true if the type_list contains the specified type, otherwise false.
//***************************************************************************
template <typename TypeList, typename T>
struct type_list_contains
: public etl::integral_constant<bool, etl::is_same<typename TypeList::type, T>::value ? true : type_list_contains<typename TypeList::tail, T>::value>
template <typename T, typename TTypes>
struct type_list_contains;
template <typename T, typename... TTypes>
struct type_list_contains<etl::type_list<TTypes...>, T>
: public etl::integral_constant<bool, etl::is_one_of<T, TTypes...>::value>
{
};
@ -217,77 +201,44 @@ namespace etl
};
#if ETL_USING_CPP17
template <typename TypeList, typename T>
inline constexpr bool type_list_contains_v = etl::type_list_contains<TypeList, T>::value;
template <typename TTypeList, typename T>
inline constexpr bool type_list_contains_v = etl::type_list_contains<TTypeList, T>::value;
#endif
//***************************************************************************
/// Defines an integral constant that is the index of the specified type in the type_list.
/// If the type is not in the type_list, then defined as etl::type_list_npos.
//***************************************************************************
template <typename TypeList, typename T>
struct type_list_index_of_type
: public etl::integral_constant<size_t, etl::is_same<typename TypeList::type, T>::value ? 0 :
(type_list_index_of_type<typename TypeList::tail, T>::value == etl::type_list_npos ? etl::type_list_npos :
type_list_index_of_type<typename TypeList::tail, T>::value + 1)>
{
};
template <typename T>
struct type_list_index_of_type<type_list<>, T>
: public etl::integral_constant<size_t, etl::type_list_npos>
{
};
#if ETL_USING_CPP17
template <typename TypeList, typename T>
inline constexpr size_t type_list_index_of_v = etl::type_list_index_of_type<TypeList, T>::value;
#endif
//***************************************************************************
/// Defines type as the type found at Index in the type_list.
/// Static asserts if Index is out of range.
//***************************************************************************
template <typename TypeList, size_t Index>
struct type_list_type_at_index
{
ETL_STATIC_ASSERT(Index <= type_list_size<TypeList>::value, "etl::type_list_type_at_index out of range");
using type = nth_type_t<Index, TypeList>;
};
template <typename TypeList, size_t Index>
using type_list_type_at_index_t = typename type_list_type_at_index<TypeList, Index>::type;
//***************************************************************************
/// Defines an integral constant that is maximum sizeof all types in the type_list.
/// If the type_list is empty, then defined as 0.
//***************************************************************************
template <typename TypeList>
struct type_list_max_sizeof_type
: public etl::integral_constant<size_t, etl::max(sizeof(typename TypeList::type), type_list_max_sizeof_type<typename TypeList::tail>::value)>
template <typename T>
struct type_list_max_size;
template <typename... TTypes>
struct type_list_max_size<etl::type_list<TTypes...>>
: public etl::integral_constant<size_t, etl::largest<TTypes...>::size>
{
};
template <>
struct type_list_max_sizeof_type<type_list<>>
struct type_list_max_size<type_list<>>
: public etl::integral_constant<size_t, 0>
{
};
#if ETL_USING_CPP17
template <typename TypeList>
inline constexpr size_t type_list_max_sizeof_type_v = etl::type_list_max_sizeof_type<TypeList>::value;
template <typename TTypeList>
inline constexpr size_t type_list_max_size_v = etl::type_list_max_size<TTypeList>::value;
#endif
//***************************************************************************
/// Defines an integral constant that is maximum alignment all types in the type_list.
/// If the type_list is empty, then defined as 1.
//***************************************************************************
template <typename TypeList>
struct type_list_max_alignment
: public etl::integral_constant<size_t, etl::max(etl::alignment_of<typename TypeList::type>::value,
type_list_max_alignment<typename TypeList::tail>::value)>
template <typename T>
struct type_list_max_alignment;
template <typename... TTypes>
struct type_list_max_alignment<etl::type_list<TTypes...>>
: public etl::integral_constant<size_t, etl::largest<TTypes...>::alignment>
{
};
@ -298,9 +249,44 @@ namespace etl
};
#if ETL_USING_CPP17
template <typename TypeList>
inline constexpr size_t type_list_max_alignment_v = etl::type_list_max_alignment<TypeList>::value;
template <typename TTypeList>
inline constexpr size_t type_list_max_alignment_v = etl::type_list_max_alignment<TTypeList>::value;
#endif
//***************************************************************************
/// Declares a new type_list by selecting types from a given type_list, according to an index sequence.
//***************************************************************************
template <typename TTypeList, size_t... Indices>
struct type_list_select
{
ETL_STATIC_ASSERT((etl::is_base_of<etl::type_list<>, TTypeList>::value), "TTypeList must be an etl::type_list");
using type = type_list<type_list_type_at_index_t<TTypeList, Indices>...>;
};
template <typename TTypeList, size_t... Indices>
using type_list_select_t = typename type_list_select<TTypeList, Indices...>::type;
//***************************************************************************
/// Concatenates two or more type_lists.
//***************************************************************************
template <typename... TTypes>
struct type_list_cat;
template <typename... TTypes1, typename... TTypes2, typename... TTail>
struct type_list_cat<etl::type_list<TTypes1...>, etl::type_list<TTypes2...>, TTail...>
{
using type = typename type_list_cat<etl::type_list<TTypes1..., TTypes2...>, TTail...>::type;
};
template <typename T>
struct type_list_cat<T>
{
using type = T;
};
template <typename... TypeLists>
using type_list_cat_t = typename type_list_cat<TypeLists...>::type;
}
#endif

View File

@ -149,6 +149,7 @@ add_executable(etl_tests
test_hfsm.cpp
test_hfsm_recurse_to_inner_state_on_start.cpp
test_histogram.cpp
test_index_of_type.cpp
test_indirect_vector.cpp
test_indirect_vector_external_buffer.cpp
test_instance_count.cpp

View File

@ -37,16 +37,6 @@ namespace
#if ETL_USING_CPP11
SUITE(test_type_list)
{
//*************************************************************************
TEST(test_nth_type)
{
typedef etl::type_list<char, int, uint32_t> t1;
CHECK_TRUE((std::is_same<etl::nth_type<0, t1>::type, char>::value));
CHECK_TRUE((std::is_same<etl::nth_type<1, t1>::type, int>::value));
CHECK_TRUE((std::is_same<etl::nth_type<2, t1>::type, uint32_t>::value));
}
//*************************************************************************
TEST(test_type_list_select)
{
@ -54,6 +44,7 @@ namespace
typedef etl::type_list<char, uint32_t> t2;
CHECK_TRUE((std::is_same<etl::type_list_select<t1, 0, 2>::type, t2>::value));
CHECK_TRUE((std::is_same<etl::type_list_select_t<t1, 0, 2>, t2>::value));
}
//*************************************************************************
@ -61,46 +52,54 @@ namespace
{
typedef etl::type_list<char, int, uint32_t> t1;
typedef etl::type_list<char, uint32_t> t2;
typedef etl::type_list<> t3;
CHECK_EQUAL(etl::type_list_size<t1>::value, 3);
CHECK_EQUAL(etl::type_list_size<t2>::value, 2);
CHECK_EQUAL(etl::type_list_size<t3>::value, 0);
}
//*************************************************************************
TEST(test_type_list_cat)
{
typedef etl::type_list<char, int, uint32_t> t1;
typedef etl::type_list<uint8_t, uint16_t> t2;
typedef etl::type_list<uint8_t, uint16_t> t2;
typedef etl::type_list<> t3;
typedef etl::type_list<char, int, uint32_t, uint8_t, uint16_t> t_cat1;
typedef etl::type_list<char, int, uint32_t, uint8_t, bool> t_cat2;
typedef etl::type_list<char, int, uint32_t, uint8_t, bool> t_cat2;
CHECK_TRUE((std::is_same<etl::type_list_cat<t1, t2>::type, t_cat1>::value));
CHECK_FALSE((std::is_same<etl::type_list_cat<t1, t2>::type, t_cat2>::value));
CHECK_TRUE((std::is_same<etl::type_list_cat<t1, t2>::type, t_cat1>::value));
CHECK_TRUE((std::is_same<etl::type_list_cat<t1, t2, t3>::type, t_cat1>::value));
CHECK_FALSE((std::is_same<etl::type_list_cat<t1, t2>::type, t_cat2>::value));
CHECK_TRUE((std::is_same<etl::type_list_cat_t<t1, t2>, t_cat1>::value));
CHECK_TRUE((std::is_same<etl::type_list_cat_t<t1, t2, t3>, t_cat1>::value));
CHECK_FALSE((std::is_same<etl::type_list_cat_t<t1, t2>, t_cat2>::value));
}
//*************************************************************************
TEST(test_type_list_contains)
{
typedef etl::type_list<char, int, uint32_t> t1;
typedef etl::type_list<uint8_t, uint16_t> t2;
typedef etl::type_list<uint8_t, uint16_t> t2;
typedef etl::type_list<uint16_t> t3;
typedef etl::type_list<> t4;
CHECK_TRUE((etl::type_list_contains<t1, char>::value));
CHECK_TRUE((etl::type_list_contains<t1, char>::value));
CHECK_FALSE((etl::type_list_contains<t1, uint8_t>::value));
CHECK_FALSE((etl::type_list_contains<t2, int>::value));
CHECK_TRUE((etl::type_list_contains<t2, uint16_t>::value));
CHECK_TRUE((etl::type_list_contains<t3, uint16_t>::value));
CHECK_TRUE((etl::type_list_contains<t2, uint16_t>::value));
CHECK_TRUE((etl::type_list_contains<t3, uint16_t>::value));
CHECK_FALSE((etl::type_list_contains<t3, uint32_t>::value));
CHECK_FALSE((etl::type_list_contains<t4, uint32_t>::value));
#if ETL_USING_CPP17
CHECK_TRUE((etl::type_list_contains_v<t1, char>));
CHECK_TRUE((etl::type_list_contains_v<t1, char>));
CHECK_FALSE((etl::type_list_contains_v<t1, uint8_t>));
CHECK_FALSE((etl::type_list_contains_v<t2, int>));
CHECK_TRUE((etl::type_list_contains_v<t2, uint16_t>));
CHECK_TRUE((etl::type_list_contains_v<t3, uint16_t>));
CHECK_TRUE((etl::type_list_contains_v<t2, uint16_t>));
CHECK_TRUE((etl::type_list_contains_v<t3, uint16_t>));
CHECK_FALSE((etl::type_list_contains_v<t3, uint32_t>));
CHECK_FALSE((etl::type_list_contains_v<t4, uint32_t>));
#endif
@ -147,16 +146,16 @@ namespace
typedef etl::type_list<uint32_t> t3;
typedef etl::type_list<> t4;
CHECK_EQUAL(etl::type_list_max_sizeof_type<t1>::value, 4);
CHECK_EQUAL(etl::type_list_max_sizeof_type<t2>::value, 2);
CHECK_EQUAL(etl::type_list_max_sizeof_type<t3>::value, 4);
CHECK_EQUAL(etl::type_list_max_sizeof_type<t4>::value, 0);
CHECK_EQUAL(etl::type_list_max_size<t1>::value, 4);
CHECK_EQUAL(etl::type_list_max_size<t2>::value, 2);
CHECK_EQUAL(etl::type_list_max_size<t3>::value, 4);
CHECK_EQUAL(etl::type_list_max_size<t4>::value, 0);
#if ETL_USING_CPP17
CHECK_EQUAL((etl::type_list_max_sizeof_type_v<t1>), 4);
CHECK_EQUAL((etl::type_list_max_sizeof_type_v<t2>), 2);
CHECK_EQUAL((etl::type_list_max_sizeof_type_v<t3>), 4);
CHECK_EQUAL((etl::type_list_max_sizeof_type_v<t4>), 0);
CHECK_EQUAL((etl::type_list_max_size_v<t1>), 4);
CHECK_EQUAL((etl::type_list_max_size_v<t2>), 2);
CHECK_EQUAL((etl::type_list_max_size_v<t3>), 4);
CHECK_EQUAL((etl::type_list_max_size_v<t4>), 0);
#endif
}

View File

@ -3169,6 +3169,7 @@
<ClInclude Include="..\..\include\etl\expected.h" />
<ClInclude Include="..\..\include\etl\function_traits.h" />
<ClInclude Include="..\..\include\etl\gcd.h" />
<ClInclude Include="..\..\include\etl\index_of_type.h" />
<ClInclude Include="..\..\include\etl\lcm.h" />
<ClInclude Include="..\..\include\etl\math.h" />
<ClInclude Include="..\..\include\etl\message_broker.h" />
@ -8477,6 +8478,7 @@
<ClCompile Include="..\test_expected.cpp" />
<ClCompile Include="..\test_function_traits.cpp" />
<ClCompile Include="..\test_hfsm_recurse_to_inner_state_on_start.cpp" />
<ClCompile Include="..\test_index_of_type.cpp" />
<ClCompile Include="..\test_intrusive_links.cpp" />
<ClCompile Include="..\test_macros.cpp" />
<ClCompile Include="..\test_math.cpp" />

View File

@ -1431,6 +1431,9 @@
<ClInclude Include="..\..\include\etl\type_list.h">
<Filter>ETL\Utilities</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\index_of_type.h">
<Filter>ETL\Utilities</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\test_string_char.cpp">
@ -3434,6 +3437,9 @@
<ClCompile Include="..\test_type_list.cpp">
<Filter>Tests\Types</Filter>
</ClCompile>
<ClCompile Include="..\test_index_of_type.cpp">
<Filter>Tests\Types</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\library.properties">