Merge branch 'pull-request/#1044-Add-traits-to-type_list' into development

This commit is contained in:
John Wellbelove 2025-03-16 19:10:06 +00:00
commit bcf5ec4985
11 changed files with 534 additions and 171 deletions

View File

@ -0,0 +1,80 @@
/******************************************************************************
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_INDEX_OF_TYPE_INCLUDED
#define ETL_INDEX_OF_TYPE_INCLUDED
#include "platform.h"
#include "static_assert.h"
#include "integral_limits.h"
namespace etl
{
#if ETL_USING_CPP11
//***************************************************************************
/// Defines a no-position constant.
//***************************************************************************
static ETL_CONSTANT size_t index_of_type_npos = etl::integral_limits<size_t>::max;
//***************************************************************************
/// Finds the index of a type in a variadic type parameter.
//***************************************************************************
template <typename T, typename... TTypes>
struct index_of_type;
//***************************************************************************
/// Finds the index of a type in a variadic type parameter.
//***************************************************************************
template <typename T, typename T1, typename... TRest>
struct index_of_type<T, T1, TRest...> : public etl::integral_constant<size_t, etl::is_same<T, T1>::value ? 0 :
(etl::index_of_type<T, TRest...>::value == etl::index_of_type_npos ? etl::index_of_type_npos :
etl::index_of_type<T, TRest...>::value + 1)>
{
};
//***************************************************************************
/// Finds the index of a type in a variadic type parameter.
/// No types left.
//***************************************************************************
template <typename T>
struct index_of_type<T> : public etl::integral_constant<size_t, etl::index_of_type_npos>
{
};
#if ETL_USING_CPP17
//***************************************************************************
/// Finds the index of a type in a variadic type parameter.
//***************************************************************************
template <typename T, typename... TTypes>
inline constexpr size_t index_of_type_v = etl::index_of_type<T, TTypes...>::value;
#endif
#endif
}
#endif

View File

@ -322,7 +322,10 @@ namespace etl
if (p_next != &this->terminator)
{
link_type* p_unlinked = etl::unlink_after<link_type>(link);
p_unlinked->clear();
if (p_unlinked != ETL_NULLPTR)
{
p_unlinked->clear();
}
--current_size;
}
}

View File

@ -31,13 +31,14 @@ SOFTWARE.
#include "../platform.h"
#include "../utility.h"
#include "../largest.h"
#include "../nth_type.h"
#include "../exception.h"
#include "../type_traits.h"
#include "../integral_limits.h"
#include "../static_assert.h"
#include "../alignment.h"
#include "../error_handler.h"
#include "../parameter_pack.h"
#include "../type_list.h"
#include "../placement_new.h"
#include "../visitor.h"
#include "../memory.h"
@ -66,82 +67,6 @@ namespace etl
{
namespace private_variant
{
//***************************************************************************
// This is a copy of the normal etl::parameter_pack, but without the static_assert
// so that the C++11 versions of do_visitor() & do_operator() do not throw a compile time error.
//***************************************************************************
template <typename... TTypes>
class parameter_pack
{
public:
static constexpr size_t size = sizeof...(TTypes);
//***************************************************************************
/// index_of_type
//***************************************************************************
template <typename T>
class index_of_type
{
private:
using type = etl::remove_cvref_t<T>;
//***********************************
template <typename Type, typename T1, typename... TRest>
struct index_of_type_helper
{
static constexpr size_t value = etl::is_same<Type, T1>::value ? 1 : 1 + index_of_type_helper<Type, TRest...>::value;
};
//***********************************
template <typename Type, typename T1>
struct index_of_type_helper<Type, T1>
{
static constexpr size_t value = 1UL;
};
public:
static_assert(etl::is_one_of<type, TTypes...>::value, "T is not in parameter pack");
/// The index value.
static constexpr size_t value = index_of_type_helper<type, TTypes...>::value - 1;
};
//***************************************************************************
/// type_from_index
//***************************************************************************
template <size_t I>
class type_from_index
{
private:
//***********************************
template <size_t II, size_t N, typename T1, typename... TRest>
struct type_from_index_helper
{
using type = typename etl::conditional<II == N, T1, typename type_from_index_helper<II, N + 1, TRest...>::type>::type;
};
//***********************************
template <size_t II, size_t N, typename T1>
struct type_from_index_helper<II, N, T1>
{
using type = T1;
};
public:
/// Template alias
using type = typename type_from_index_helper<I, 0, TTypes...>::type;
};
//***********************************
template <size_t I>
using type_from_index_t = typename type_from_index<I>::type;
};
//*******************************************
// The traits an object may have.
//*******************************************
@ -327,7 +252,7 @@ namespace etl
template <size_t Index, typename... TTypes>
struct variant_alternative<Index, etl::variant<TTypes...>>
{
using type = typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<Index>::type;
using type = nth_type_t<Index, TTypes...>;
};
template <size_t Index, typename T>
@ -529,13 +454,13 @@ namespace etl
// Get the index of a type.
//*******************************************
template <typename T>
using index_of_type = typename etl::private_variant::parameter_pack<TTypes...>::template index_of_type<etl::remove_cvref_t<T>>;
using index_of_type = etl::type_list_index_of_type<etl::type_list<TTypes...>, etl::remove_cvref_t<T>>;
//*******************************************
// Get the type from the index.
//*******************************************
template <size_t Index>
using type_from_index = typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<Index>::type;
using type_from_index = typename etl::type_list_type_at_index<etl::type_list<TTypes...>, Index>::type;
public:
@ -546,7 +471,7 @@ namespace etl
#include "diagnostic_uninitialized_push.h"
ETL_CONSTEXPR14 variant()
{
using type = typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<0U>::type;
using type = type_from_index<0U>;
default_construct_in_place<type>(data);
operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
@ -592,7 +517,7 @@ namespace etl
ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, TArgs&&... args)
: type_id(Index)
{
using type = typename private_variant::parameter_pack<TTypes...>:: template type_from_index_t<Index>;
using type = type_from_index<Index>;
static_assert(etl::is_one_of<type, TTypes...> ::value, "Unsupported type");
construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
@ -625,7 +550,7 @@ namespace etl
ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, std::initializer_list<U> init, TArgs&&... args)
: type_id(Index)
{
using type = typename private_variant::parameter_pack<TTypes...>:: template type_from_index_t<Index>;
using type = type_from_index<Index>;
static_assert(etl::is_one_of<type, TTypes...> ::value, "Unsupported type");
construct_in_place_args<type>(data, init, etl::forward<TArgs>(args)...);
@ -715,7 +640,7 @@ namespace etl
operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
type_id = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
type_id = index_of_type<T>::value;
return *static_cast<T*>(data);
}
@ -737,7 +662,7 @@ namespace etl
operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
type_id = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
type_id = index_of_type<T>::value;
return *static_cast<T*>(data);
}
@ -747,9 +672,9 @@ namespace etl
/// Emplace by index with variadic constructor parameters.
//***************************************************************************
template <size_t Index, typename... TArgs>
typename etl::variant_alternative<Index, variant<TArgs...>>::type& emplace(TArgs&&... args)
typename etl::variant_alternative<Index, variant<TTypes...>>::type& emplace(TArgs&&... args)
{
static_assert(Index < etl::private_variant::parameter_pack<TTypes...>::size, "Index out of range");
static_assert(Index < sizeof...(TTypes), "Index out of range");
using type = type_from_index<Index>;
@ -769,9 +694,9 @@ namespace etl
/// Emplace by index with variadic constructor parameters.
//***************************************************************************
template <size_t Index, typename U, typename... TArgs>
typename etl::variant_alternative<Index, variant<TArgs...>>::type& emplace(std::initializer_list<U> il, TArgs&&... args)
typename etl::variant_alternative<Index, variant<TTypes...>>::type& emplace(std::initializer_list<U> il, TArgs&&... args)
{
static_assert(Index < etl::private_variant::parameter_pack<TTypes...>::size, "Index out of range");
static_assert(Index < sizeof...(TTypes), "Index out of range");
using type = type_from_index<Index>;
@ -803,7 +728,7 @@ namespace etl
construct_in_place<type>(data, etl::forward<T>(value));
operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
type_id = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<type>::value;
type_id = index_of_type<type>::value;
return *this;
}
@ -896,7 +821,7 @@ namespace etl
template <typename T, etl::enable_if_t<is_supported_type<T>(), int> = 0>
constexpr bool is_type() const noexcept
{
return (type_id == etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value);
return (type_id == index_of_type<T>::value);
}
//***************************************************************************
@ -1469,7 +1394,7 @@ namespace etl
template <typename T, typename... TTypes>
ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) noexcept
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
return (Index == variant_npos) ? false : (v.index() == Index);
}
@ -1560,7 +1485,7 @@ namespace etl
template <typename T, typename... TTypes>
ETL_CONSTEXPR14 T& get(etl::variant<TTypes...>& v)
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
return get<Index>(v);
}
@ -1569,7 +1494,7 @@ namespace etl
template <typename T, typename... TTypes>
ETL_CONSTEXPR14 T&& get(etl::variant<TTypes...>&& v)
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
return get<Index>(etl::move(v));
}
@ -1578,7 +1503,7 @@ namespace etl
template <typename T, typename... TTypes>
ETL_CONSTEXPR14 const T& get(const etl::variant<TTypes...>& v)
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
return get<Index>(v);
}
@ -1587,7 +1512,7 @@ namespace etl
template <typename T, typename... TTypes>
ETL_CONSTEXPR14 const T&& get(const etl::variant<TTypes...>&& v)
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
return get<Index>(etl::move(v));
}
@ -1628,7 +1553,7 @@ namespace etl
template< class T, typename... TTypes >
ETL_CONSTEXPR14 etl::add_pointer_t<T> get_if(etl::variant<TTypes...>* pv) noexcept
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
if ((pv != nullptr) && (pv->index() == Index))
{
@ -1644,7 +1569,7 @@ namespace etl
template< typename T, typename... TTypes >
ETL_CONSTEXPR14 etl::add_pointer_t<const T> get_if(const etl::variant<TTypes...>* pv) noexcept
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
if ((pv != nullptr) && (pv->index() == Index))
{

View File

@ -30,14 +30,23 @@ SOFTWARE.
#define ETL_TYPE_LIST_INCLUDED
#include "platform.h"
#include "nth_type.h"
#include "algorithm.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
{
//***************************************************************************
/// Defines a no-position constant.
//***************************************************************************
static ETL_CONSTANT size_t type_list_npos = etl::integral_limits<size_t>::max;
//***************************************************************************
/// Type list forward declaration.
//***************************************************************************
@ -61,13 +70,24 @@ 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.
//***************************************************************************
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;
@ -86,7 +106,8 @@ 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;
@ -99,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>
@ -156,30 +137,156 @@ 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;
};
template <typename TTypeList>
struct type_list_type_at_index<TTypeList, 0>
{
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 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>
{
};
template <typename T>
struct type_list_contains<type_list<>, T>
: public etl::integral_constant<bool, false>
{
};
#if ETL_USING_CPP17
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 maximum sizeof all types in the type_list.
/// If the type_list is empty, then defined as 0.
//***************************************************************************
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_size<type_list<>>
: public etl::integral_constant<size_t, 0>
{
};
#if ETL_USING_CPP17
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 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>
{
};
template <>
struct type_list_max_alignment<type_list<>>
: public etl::integral_constant<size_t, 1>
{
};
#if ETL_USING_CPP17
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.
/// Specialisation for 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
@ -286,6 +287,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

View File

@ -0,0 +1,58 @@
/******************************************************************************
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 "unit_test_framework.h"
#include "etl/index_of_type.h"
#include <type_traits>
namespace
{
SUITE(test_index_of_type)
{
//*************************************************************************
TEST(test_index_of_type)
{
CHECK_EQUAL(0, (etl::index_of_type<int, int, long, double>::value));
CHECK_EQUAL(1, (etl::index_of_type<long, int, long, double>::value));
CHECK_EQUAL(2, (etl::index_of_type<double, int, long, double>::value));
CHECK_EQUAL(etl::index_of_type_npos, (etl::index_of_type<float, int, long, double>::value));
}
//*************************************************************************
#if ETL_USING_CPP17
TEST(test_index_of_type_v)
{
CHECK_EQUAL(0, (etl::index_of_type_v<int, int, long, double>));
CHECK_EQUAL(1, (etl::index_of_type_v<long, int, long, double>));
CHECK_EQUAL(2, (etl::index_of_type_v<double, int, long, double>));
CHECK_EQUAL(etl::index_of_type_npos, (etl::index_of_type_v<float, int, long, double>));
}
#endif
}
}

View File

@ -37,6 +37,7 @@ SOFTWARE.
#include <vector>
#include "etl/map.h"
#include "etl/string.h"
#include "data.h"
@ -1575,7 +1576,7 @@ namespace
#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED)
TEST_FIXTURE(SetupFixture, test_map_template_deduction)
{
using Pair = std::pair<const std::string, int>;
using Pair = std::pair<const etl::string<1>, int>;
etl::map data { Pair{"0", 0}, Pair{"1", 1}, Pair{"2", 2}, Pair{"3", 3}, Pair{"4", 4}, Pair{"5", 5} };
@ -1596,9 +1597,9 @@ namespace
#if ETL_HAS_INITIALIZER_LIST
TEST_FIXTURE(SetupFixture, test_make_map)
{
using Pair = ETL_OR_STD::pair<const std::string, int>;
using Pair = ETL_OR_STD::pair<const etl::string<1>, int>;
auto data = etl::make_map<std::string, int, std::less<std::string>>(Pair{ "0", 0 }, Pair{ "1", 1 }, Pair{ "2", 2 }, Pair{ "3", 3 }, Pair{ "4", 4 }, Pair{ "5", 5 });
auto data = etl::make_map<const etl::string<1>, int, std::less<etl::string<1>>>(Pair{ "0", 0 }, Pair{ "1", 1 }, Pair{ "2", 2 }, Pair{ "3", 3 }, Pair{ "4", 4 }, Pair{ "5", 5 });
auto v = *data.begin();
using Type = decltype(v);

View File

@ -341,14 +341,7 @@ namespace
etl::multi_span<int>::iterator ms_itr = ms_int.begin();
etl::multi_span<int>::iterator ms_end_itr = ms_int.end();
while (ms_itr != ms_end_itr)
{
// Fill the multi span
*ms_itr++ = *exp_itr++;
}
ms_itr = ms_int.begin();
exp_itr = expected.begin();
std::copy(ms_itr, ms_end_itr, exp_itr);
while (ms_itr != ms_end_itr)
{
@ -554,10 +547,7 @@ namespace
multi_span_type::reverse_iterator ms_itr = ms_int.rbegin();
multi_span_type::reverse_iterator ms_end_itr = ms_int.rend();
while (ms_itr != ms_end_itr)
{
*ms_itr++ = *exp_itr++;
}
std::copy(ms_itr, ms_end_itr, exp_itr);
while (ms_itr != ms_end_itr)
{

185
test/test_type_list.cpp Normal file
View File

@ -0,0 +1,185 @@
/******************************************************************************
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_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));
CHECK_TRUE((std::is_same<etl::type_list_select_t<t1, 0, 2>, t2>::value));
}
//*************************************************************************
TEST(test_type_list_size)
{
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<> 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;
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<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_type)
{
typedef etl::type_list<char, int, uint32_t> t1;
typedef etl::type_list<> t2;
CHECK_EQUAL((etl::type_list_index_of_type<t1, char>::value), 0);
CHECK_EQUAL((etl::type_list_index_of_type<t1, int>::value), 1);
CHECK_EQUAL((etl::type_list_index_of_type<t1, uint32_t>::value), 2);
CHECK_EQUAL((etl::type_list_index_of_type<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_type_at_index)
{
typedef etl::type_list<char, int, uint32_t> t1;
CHECK_TRUE((std::is_same<char, etl::type_list_type_at_index<t1, 0>::type>::value));
CHECK_TRUE((std::is_same<int, etl::type_list_type_at_index<t1, 1>::type>::value));
CHECK_TRUE((std::is_same<uint32_t, etl::type_list_type_at_index<t1, 2>::type>::value));
CHECK_TRUE((std::is_same<char, etl::type_list_type_at_index_t<t1, 0>>::value));
CHECK_TRUE((std::is_same<int, etl::type_list_type_at_index_t<t1, 1>>::value));
CHECK_TRUE((std::is_same<uint32_t, etl::type_list_type_at_index_t<t1, 2>>::value));
}
//*************************************************************************
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_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_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
}
//*************************************************************************
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
}

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" />
@ -9453,6 +9455,7 @@
<ClCompile Include="..\test_to_u8string.cpp" />
<ClCompile Include="..\test_to_wstring.cpp" />
<ClCompile Include="..\test_type_def.cpp" />
<ClCompile Include="..\test_type_list.cpp" />
<ClCompile Include="..\test_type_lookup.cpp" />
<ClCompile Include="..\test_type_select.cpp" />
<ClCompile Include="..\test_type_traits.cpp" />

View File

@ -1429,7 +1429,10 @@
<Filter>UnitTest++\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\type_list.h">
<Filter>UnitTest++\Header Files</Filter>
<Filter>ETL\Utilities</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\index_of_type.h">
<Filter>ETL\Utilities</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
@ -3431,6 +3434,12 @@
<ClCompile Include="..\syntax_check\singleton_base.h.t.cpp">
<Filter>Tests\Syntax Checks\Source</Filter>
</ClCompile>
<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">