Add traits to type_list (#1044)

This commit is contained in:
Roland Reichwein 2025-03-09 10:41:15 +01:00 committed by John Wellbelove
parent a6615a419d
commit d9d9ae1e53
3 changed files with 264 additions and 0 deletions

View File

@ -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<size_t>::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 <typename... TTypes>
struct recursion_helper
{
using type = type_list<TTypes...>;
};
}
//***************************************************************************
/// Recursive type list implementation for multiple types.
//***************************************************************************
@ -68,6 +86,7 @@ namespace etl
struct type_list<THead, TTail...> : type_list<TTail...>
{
using type = THead;
using tail = typename private_type_list::recursion_helper<TTail...>::type;
static constexpr size_t size = sizeof...(TTail) + 1U;
@ -87,6 +106,7 @@ namespace etl
struct type_list<THead> : 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<etl::type_list<TTypes1..., TTypes2...>, TTail...>::type;
};
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>
struct type_list_contains<type_list<>, T>
: public etl::integral_constant<bool, false>
{
};
#if ETL_USING_CPP17
template<typename TypeList, typename T>
inline constexpr bool type_list_contains_v = etl::type_list_contains<TypeList, T>::value;
#endif
template<typename TypeList, typename T>
struct type_list_index_of
: public etl::integral_constant<size_t, etl::is_same<typename TypeList::type, T>::value ? 0 :
(type_list_index_of<typename TypeList::tail, T>::value == type_list_npos ?
type_list_npos : type_list_index_of<typename TypeList::tail, T>::value + 1)>
{
};
template<typename T>
struct type_list_index_of<type_list<>, T>
: public etl::integral_constant<size_t, 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<TypeList, T>::value;
#endif
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<>
struct type_list_max_sizeof_type<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;
#endif
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<>
struct type_list_max_alignment<type_list<>>
: public etl::integral_constant<size_t, 1>
{
};
#if ETL_USING_CPP17
template<typename TypeList>
inline constexpr size_t type_list_max_alignment_v = etl::type_list_max_alignment<TypeList>::value;
#endif
}
#endif

View File

@ -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

172
test/test_type_list.cpp Normal file
View File

@ -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 <type_traits>
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)
{
typedef etl::type_list<char, int, uint32_t> t1;
typedef etl::type_list<char, uint32_t> t2;
CHECK_TRUE((std::is_same<etl::type_list_select<t1, 0, 2>::type, t2>::value));
}
//*************************************************************************
TEST(test_type_list_size)
{
typedef etl::type_list<char, int, uint32_t> t1;
typedef etl::type_list<char, uint32_t> t2;
CHECK_EQUAL(etl::type_list_size<t1>::value, 3);
CHECK_EQUAL(etl::type_list_size<t2>::value, 2);
}
//*************************************************************************
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<char, int, uint32_t, uint8_t, uint16_t> t_cat1;
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));
}
//*************************************************************************
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<uint16_t> t3;
typedef etl::type_list<> t4;
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_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_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_FALSE((etl::type_list_contains_v<t3, uint32_t>));
CHECK_FALSE((etl::type_list_contains_v<t4, uint32_t>));
#endif
}
//*************************************************************************
TEST(test_type_list_index_of)
{
typedef etl::type_list<char, int, uint32_t> t1;
typedef etl::type_list<> t2;
CHECK_EQUAL((etl::type_list_index_of<t1, char>::value), 0);
CHECK_EQUAL((etl::type_list_index_of<t1, int>::value), 1);
CHECK_EQUAL((etl::type_list_index_of<t1, uint32_t>::value), 2);
CHECK_EQUAL((etl::type_list_index_of<t2, uint32_t>::value), etl::type_list_npos);
#if ETL_USING_CPP17
CHECK_EQUAL((etl::type_list_index_of_v<t1, char>), 0);
CHECK_EQUAL((etl::type_list_index_of_v<t1, int>), 1);
CHECK_EQUAL((etl::type_list_index_of_v<t1, uint32_t>), 2);
CHECK_EQUAL((etl::type_list_index_of_v<t2, uint32_t>), etl::type_list_npos);
#endif
}
//*************************************************************************
TEST(test_type_list_max_sizeof_type)
{
typedef etl::type_list<char, int16_t, uint32_t> t1;
typedef etl::type_list<uint8_t, uint16_t> t2;
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);
#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);
#endif
}
//*************************************************************************
TEST(test_type_list_max_alignment)
{
typedef etl::type_list<char, int16_t, uint32_t> t1;
typedef etl::type_list<uint8_t, uint16_t> t2;
typedef etl::type_list<uint16_t> t3;
typedef etl::type_list<> t4;
CHECK_EQUAL(etl::type_list_max_alignment<t1>::value, std::alignment_of<uint32_t>::value);
CHECK_EQUAL(etl::type_list_max_alignment<t2>::value, std::alignment_of<uint16_t>::value);
CHECK_EQUAL(etl::type_list_max_alignment<t3>::value, std::alignment_of<uint16_t>::value);
CHECK_EQUAL(etl::type_list_max_alignment<t4>::value, 1);
#if ETL_USING_CPP17
CHECK_EQUAL((etl::type_list_max_alignment_v<t1>), std::alignment_of<uint32_t>::value);
CHECK_EQUAL((etl::type_list_max_alignment_v<t2>), std::alignment_of<uint16_t>::value);
CHECK_EQUAL((etl::type_list_max_alignment_v<t3>), std::alignment_of<uint16_t>::value);
CHECK_EQUAL((etl::type_list_max_alignment_v<t4>), 1);
#endif
}
};
#endif
}