Merge branch 'development' into refactor/reduce-string-flash-usage

This commit is contained in:
John Wellbelove 2026-02-25 08:47:21 +00:00 committed by GitHub
commit c1a9c09419
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 1457 additions and 23 deletions

View File

@ -48,11 +48,14 @@ namespace etl
static ETL_CONSTANT size_t type_list_npos = etl::integral_limits<size_t>::max;
//***************************************************************************
/// Type list forward declaration.
// Type list forward declaration.
//***************************************************************************
template <typename... TTypes>
struct type_list;
//***************************************************************************
/// Check if a type is an etl::type_list.
//***************************************************************************
template <typename T>
struct is_type_list : etl::false_type {};
@ -76,6 +79,7 @@ namespace etl
private:
// A type_list cannot be instantiated, so delete the constructor and assignment operators.
type_list() ETL_DELETE;
type_list(const type_list&) ETL_DELETE;
type_list& operator =(const type_list&) ETL_DELETE;
@ -106,6 +110,7 @@ namespace etl
private:
// A type_list cannot be instantiated, so delete the constructor and assignment operators.
type_list() ETL_DELETE;
type_list(const type_list&) ETL_DELETE;
type_list& operator =(const type_list&) ETL_DELETE;
@ -154,8 +159,8 @@ namespace etl
template <typename TTypeList, size_t Index>
struct type_list_type_at_index
{
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");
ETL_STATIC_ASSERT(Index < TTypeList::size, "etl::type_list_type_at_index out of range");
ETL_STATIC_ASSERT((etl::is_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;
};
@ -163,6 +168,8 @@ namespace etl
template <typename TTypeList>
struct type_list_type_at_index<TTypeList, 0>
{
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
using type = typename TTypeList::head;
};
@ -170,16 +177,18 @@ namespace etl
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.
/// Defines an integral constant that is the index of the <i>first</i> instance of specified type in the type_list.
/// If the type is not in the type_list, then defined as etl::type_list_npos.
/// Useful for type lists that do not contain duplicates, otherwise use type_list_indices_of_type.
/// Static asserts if TTypeList is not an etl::type_list.
//***************************************************************************
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 == 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");
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
};
template <typename T>
@ -193,6 +202,56 @@ namespace etl
inline constexpr size_t type_list_index_of_v = etl::type_list_index_of_type<TTypeList, T>::value;
#endif
//***************************************************************************
/// Defines an index_sequence of indices where T appears in the type_list.
/// If the type is not in the type_list, then defined as an empty index_sequence.
/// Useful for type lists that contain duplicates, otherwise use type_list_index_of_type.
/// Static asserts if TTypeList is not an etl::type_list.
//***************************************************************************
namespace private_type_list
{
template <typename TTypeList, typename T, size_t Index, typename TResult>
struct type_list_indices_of_type_impl;
// The general case, check the head type, then recurse with the rest of the types.
template <typename Head, typename... Tail, typename T, size_t Index, typename TResult>
struct type_list_indices_of_type_impl<etl::type_list<Head, Tail...>, T, Index, TResult>
{
private:
// If Head is the same as T then append a new index to the result, otherwise no change.
using next_result = etl::conditional_t<etl::is_same<Head, T>::value,
etl::index_sequence_push_back_t<TResult, Index>,
TResult>;
public:
// Recurse with the rest of the type_list, passing on the current result.
using type = typename type_list_indices_of_type_impl<etl::type_list<Tail...>, T, Index + 1U, next_result>::type;
};
// Specialisation for an empty type_list.
// This is the terminating specialisation for the general case.
template <typename T, size_t Index, typename TResult>
struct type_list_indices_of_type_impl<etl::type_list<>, T, Index, TResult>
{
using type = TResult;
};
}
template <typename TTypeList, typename T>
struct type_list_indices_of_type
{
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
using type = typename private_type_list::type_list_indices_of_type_impl<TTypeList, T, 0U, etl::index_sequence<>>::type;
};
#if ETL_USING_CPP11
template <typename TTypeList, typename T>
using type_list_indices_of_type_t = typename type_list_indices_of_type<TTypeList, T>::type;
#endif
//***************************************************************************
/// Defines a bool constant that is true if the type_list contains the specified type, otherwise false.
//***************************************************************************
@ -311,12 +370,12 @@ namespace etl
#endif
//***************************************************************************
/// Declares a new type_list by selecting types from a given type_list, according to an index sequence.
/// Declares a new type_list by selecting types from a given type_list, according to a list if indices.
//***************************************************************************
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");
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
using type = type_list<type_list_type_at_index_t<TTypeList, Indices>...>;
};
@ -324,6 +383,21 @@ namespace etl
template <typename TTypeList, size_t... Indices>
using type_list_select_t = typename type_list_select<TTypeList, Indices...>::type;
//***************************************************************************
/// Declares a new type_list by selecting types from a given type_list, according to an index sequence.
//***************************************************************************
template <typename TTypeList, typename TIndexSequence>
struct type_list_select_from_index_sequence;
template <typename TTypeList, size_t... Indices>
struct type_list_select_from_index_sequence<TTypeList, etl::index_sequence<Indices...>>
{
using type = etl::type_list_select_t<TTypeList, Indices...>;
};
template <typename TTypeList, typename TIndexSequence>
using type_list_select_from_index_sequence_t = typename type_list_select_from_index_sequence<TTypeList, TIndexSequence>::type;
//***************************************************************************
/// Concatenates two or more type_lists.
//***************************************************************************
@ -345,6 +419,345 @@ namespace etl
template <typename... TypeLists>
using type_list_cat_t = typename type_list_cat<TypeLists...>::type;
//***************************************************************************
/// Add a type to the beginning of a type_list.
//***************************************************************************
template <typename T, typename... TTypes>
struct type_list_push_front;
template <typename T, typename... TTypes>
struct type_list_push_front<etl::type_list<TTypes...>, T>
{
using type = type_list<T, TTypes...>;
};
template <typename TypeList, typename T>
using type_list_push_front_t = typename type_list_push_front<TypeList, T>::type;
//***************************************************************************
/// Add a type to the end of a type_list.
//***************************************************************************
template <typename T, typename... TTypes>
struct type_list_push_back;
template <typename T, typename... TTypes>
struct type_list_push_back<etl::type_list<TTypes...>, T>
{
using type = type_list<TTypes..., T>;
};
template <typename TypeList, typename T>
using type_list_push_back_t = typename type_list_push_back<TypeList, T>::type;
//***************************************************************************
/// Insert a type at an index in a type_list.
/// Inserts before the type currently at Index.
/// If Index == size of the type_list, the type is appended.
//***************************************************************************
template <typename TTypeList, typename T, size_t Index>
struct type_list_insert
{
private:
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
ETL_STATIC_ASSERT(Index <= TTypeList::size, "Index out of range");
using index_sequence_for_prefix = etl::make_index_sequence<Index>;
using index_sequence_for_suffix = etl::make_index_sequence_with_offset<Index, TTypeList::size - Index>;
using prefix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_prefix>;
using suffix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_suffix>;
public:
// Concatenate the prefix, new type, and suffix to create the new type list with T inserted at the correct position.
using type = etl::type_list_cat_t<prefix, etl::type_list<T>, suffix>;
};
#if ETL_USING_CPP11
template <typename TTypeList, typename T, size_t Index>
using type_list_insert_t = typename etl::type_list_insert<TTypeList, T, Index>::type;
#endif
//***************************************************************************
/// Remove a type at an index in a type_list.
//***************************************************************************
template <typename TTypeList, size_t Index>
struct type_list_remove
{
private:
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
ETL_STATIC_ASSERT(Index < TTypeList::size, "Index out of range");
using index_sequence_for_prefix = etl::make_index_sequence<Index>;
using index_sequence_for_suffix = etl::make_index_sequence_with_offset<Index + 1, TTypeList::size - Index - 1>;
using prefix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_prefix>;
using suffix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_suffix>;
public:
// Concatenate the prefix and suffix to create the new type list with the Index element removed.
using type = etl::type_list_cat_t<prefix, suffix>;
};
#if ETL_USING_CPP11
template <typename TTypeList, size_t Index>
using type_list_remove_t = typename etl::type_list_remove<TTypeList, Index>::type;
#endif
//***************************************************************************
// Remove types that satisfy a predicate from a type_list.
//***************************************************************************
namespace private_type_list
{
template <typename TTypeList, template <typename> class TPredicate>
struct type_list_remove_if_impl;
template <template <typename> class TPredicate>
struct type_list_remove_if_impl<etl::type_list<>, TPredicate>
{
using type = etl::type_list<>;
};
template <typename Head, typename... Tail, template <typename> class TPredicate>
struct type_list_remove_if_impl<etl::type_list<Head, Tail...>, TPredicate>
{
private:
using rest = typename type_list_remove_if_impl<etl::type_list<Tail...>, TPredicate>::type;
public:
using type = typename etl::conditional<TPredicate<Head>::value,
rest,
etl::type_list_push_front_t<rest, Head>>::type;
};
}
//***************************************************************************
/// Remove types that satisfy a predicate from a type_list.
/// Predicate must be: template <typename T> struct Pred : etl::bool_constant<...> {};
//***************************************************************************
template <typename TTypeList, template <typename> class TPredicate>
struct type_list_remove_if
{
private:
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
public:
using type = typename private_type_list::type_list_remove_if_impl<TTypeList, TPredicate>::type;
};
#if ETL_USING_CPP11
template <typename TTypeList, template <typename> class TPredicate>
using type_list_remove_if_t = typename etl::type_list_remove_if<TTypeList, TPredicate>::type;
#endif
//***************************************************************************
/// Removes the first type from a type_list.
//***************************************************************************
template <typename TTypeList>
struct type_list_pop_front
{
private:
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
ETL_STATIC_ASSERT(TTypeList::size > 0U, "Cannot pop_front from an empty type_list");
public:
using type = typename TTypeList::tail;
};
#if ETL_USING_CPP11
template <typename TTypeList>
using type_list_pop_front_t = typename etl::type_list_pop_front<TTypeList>::type;
#endif
//***************************************************************************
/// Removes the last type from a type_list.
//***************************************************************************
template <typename TTypeList>
struct type_list_pop_back
{
private:
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
ETL_STATIC_ASSERT(TTypeList::size > 0U, "Cannot pop_back from an empty type_list");
public:
using type = typename etl::type_list_remove<TTypeList, TTypeList::size - 1U>::type;
};
#if ETL_USING_CPP11
template <typename TTypeList>
using type_list_pop_back_t = typename etl::type_list_pop_back<TTypeList>::type;
#endif
//***************************************************************************
// Remove duplicate types from a type_list, preserving the first occurrence.
//***************************************************************************
namespace private_type_list
{
template <typename TTypeList, typename TResult>
struct type_list_unique_impl;
// Base case: empty list, return the result.
template <typename TResult>
struct type_list_unique_impl<etl::type_list<>, TResult>
{
using type = TResult;
};
// Recursive case: Check if the head is already in the result, if not add it, then recurse on the tail.
template <typename Head, typename... Tail, typename TResult>
struct type_list_unique_impl<etl::type_list<Head, Tail...>, TResult>
{
private:
using next_result = etl::conditional_t<etl::type_list_contains<TResult, Head>::value,
TResult,
etl::type_list_push_back_t<TResult, Head>>;
public:
using type = typename type_list_unique_impl<etl::type_list<Tail...>, next_result>::type;
};
}
//***************************************************************************
/// Defines a new type_list by removing duplicate types from a given type_list, preserving the first occurrence.
//***************************************************************************
template <typename TTypeList>
struct type_list_unique
{
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
using type = typename private_type_list::type_list_unique_impl<TTypeList, etl::type_list<>>::type;
};
#if ETL_USING_CPP11
template <typename TTypeList>
using type_list_unique_t = typename etl::type_list_unique<TTypeList>::type;
#endif
//***************************************************************************
/// Checks that all of the types in a type_list are unique.
//***************************************************************************
template <typename TTypeList>
struct type_list_is_unique
// Create a unique version of the type list, and check if it is the same as the original list.
// If they are the same, then all types in the original list are unique.
: etl::bool_constant<std::is_same<TTypeList, typename type_list_unique<TTypeList>::type>::value>
{
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
};
#if ETL_USING_CPP17
template <typename TTypeList>
inline constexpr bool type_list_is_unique_v = etl::type_list_is_unique<TTypeList>::value;
#endif
//***************************************************************************
/// Check if the type_list is empty.
//***************************************************************************
template <typename T>
struct type_list_is_empty;
template <>
struct type_list_is_empty<etl::type_list<>>
: etl::true_type
{
};
template <typename... TTypes>
struct type_list_is_empty<etl::type_list<TTypes...>>
: etl::false_type
{
};
#if ETL_USING_CPP17
template <typename... TTypes>
inline constexpr bool type_list_is_empty_v = type_list_is_empty<TTypes...>::value;
#endif
//***************************************************************************
/// Checks that all types in a type_list satisfy a unary predicate.
/// Predicate must be: template <typename T> struct Pred : etl::bool_constant<...> {};
//***************************************************************************
template <typename TTypeList, template <typename> class TPredicate>
struct type_list_all_of;
template <template <typename> class TPredicate, typename... TTypes>
struct type_list_all_of<etl::type_list<TTypes...>, TPredicate>
: etl::conjunction<TPredicate<TTypes>...>
{
};
template <template <typename> class TPredicate>
struct type_list_all_of<etl::type_list<>, TPredicate>
: etl::bool_constant<true>
{
};
#if ETL_USING_CPP17
template <typename TTypeList, template <typename> class TPredicate>
inline constexpr bool type_list_all_of_v = type_list_all_of<TTypeList, TPredicate>::value;
#endif
//***************************************************************************
/// Checks that any type in a type_list satisfies a unary predicate.
/// Predicate must be: template <typename T> struct Pred : etl::bool_constant<...> {};
//***************************************************************************
template <typename TTypeList, template <typename> class TPredicate>
struct type_list_any_of;
template <template <typename> class TPredicate, typename... TTypes>
struct type_list_any_of<etl::type_list<TTypes...>, TPredicate>
: etl::disjunction<TPredicate<TTypes>...>
{
};
template <template <typename> class TPredicate>
struct type_list_any_of<etl::type_list<>, TPredicate>
: etl::bool_constant<false>
{
};
#if ETL_USING_CPP17
template <typename TTypeList, template <typename> class TPredicate>
inline constexpr bool type_list_any_of_v = type_list_any_of<TTypeList, TPredicate>::value;
#endif
//***************************************************************************
/// Checks that no types in a type_list satisfy a unary predicate.
/// Predicate must be: template <typename T> struct Pred : etl::bool_constant<...> {};
//***************************************************************************
template <typename TTypeList, template <typename> class TPredicate>
struct type_list_none_of;
template <template <typename> class TPredicate, typename... TTypes>
struct type_list_none_of<etl::type_list<TTypes...>, TPredicate>
: etl::negation<etl::disjunction<TPredicate<TTypes>...>>
{
};
template <template <typename> class TPredicate>
struct type_list_none_of<etl::type_list<>, TPredicate>
: etl::bool_constant<true>
{
};
#if ETL_USING_CPP17
template <typename TTypeList, template <typename> class TPredicate>
inline constexpr bool type_list_none_of_v = type_list_none_of<TTypeList, TPredicate>::value;
#endif
//***************************************************************************
/// Checks that two type lists are convertible.
/// Static asserts if the type lists are not the same length.
@ -355,15 +768,15 @@ namespace etl
// Specialization: both lists empty, convertible
template <>
struct type_lists_are_convertible<etl::type_list<>, etl::type_list<>>
struct type_lists_are_convertible<etl::type_list<>, etl::type_list<>>
: public etl::true_type
{
};
// Recursive case: check head types, then recurse
template <typename TFromHead, typename... TFromTail, typename TToHead, typename... TToTail>
struct type_lists_are_convertible<etl::type_list<TFromHead, TFromTail...>, etl::type_list<TToHead, TToTail...>>
: public etl::bool_constant<etl::is_convertible<TFromHead, TToHead>::value &&
struct type_lists_are_convertible<etl::type_list<TFromHead, TFromTail...>, etl::type_list<TToHead, TToTail...>>
: public etl::bool_constant<etl::is_convertible<TFromHead, TToHead>::value &&
etl::type_lists_are_convertible<etl::type_list<TFromTail...>, etl::type_list<TToTail...>>::value>
{
static_assert(sizeof...(TFromTail) == sizeof...(TToTail), "Type lists are not the same length");
@ -373,6 +786,175 @@ namespace etl
template <typename TFromList, typename TToList>
inline constexpr bool type_lists_are_convertible_v = etl::type_lists_are_convertible<TFromList, TToList>::value;
#endif
namespace private_type_list
{
//*********************************
template <typename TTypeList, template <typename, typename> class TCompare>
struct type_list_is_sorted_impl;
//*********************************
// Empty list is sorted
template <template <typename, typename> class TCompare>
struct type_list_is_sorted_impl<etl::type_list<>, TCompare>
: etl::true_type
{
};
//*********************************
// Single element list is sorted
template <typename T0, template <typename, typename> class TCompare>
struct type_list_is_sorted_impl<etl::type_list<T0>, TCompare>
: etl::true_type
{
};
//*********************************
// Ensure that the list is sorted.
// Recursively compare the head to the next element to ensure that the list is sorted.
template <typename Head, typename Next, typename... Tail, template <typename, typename> class TCompare>
struct type_list_is_sorted_impl<etl::type_list<Head, Next, Tail...>, TCompare>
: etl::bool_constant<!TCompare<Next, Head>::value &&
type_list_is_sorted_impl<etl::type_list<Next, Tail...>, TCompare>::value>
{
};
}
//*****************************************************************************
/// Checks if a type_list is sorted according to TCompare
/// Static asserts if TTypeList is not an etl::type_list.
/// Comparator must be: template <typename A, typename B> struct Compare : etl::bool_constant<...> {};
//*****************************************************************************
template <typename TTypeList, template <typename, typename> class TCompare>
struct type_list_is_sorted : public private_type_list::type_list_is_sorted_impl<TTypeList, TCompare>
{
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
};
#if ETL_USING_CPP17
template <typename TTypeList, template <typename, typename> class TCompare>
inline constexpr bool type_list_is_sorted_v = etl::type_list_is_sorted<TTypeList, TCompare>::value;
#endif
//*****************************************************************************
namespace private_type_list
{
//*********************************
template <bool InsertBefore, typename Head, typename T, template <typename, typename> class TCompare, typename... Tail>
struct insert_sorted_impl;
//*********************************
template <typename TSortedList, typename T, template <typename, typename> class TCompare>
struct type_list_insert_sorted_impl;
//*********************************
// Insert T into sorted list using TCompare
// Empty list -> T becomes the list
template <typename T, template <typename, typename> class TCompare>
struct type_list_insert_sorted_impl<etl::type_list<>, T, TCompare>
{
using type = etl::type_list<T>;
};
//*********************************
// Insert T into the correct position in the sorted list, as determined by TCompare
template <typename Head, typename... Tail, typename T, template <typename, typename> class TCompare>
struct type_list_insert_sorted_impl<etl::type_list<Head, Tail...>, T, TCompare>
{
using type = typename insert_sorted_impl<TCompare<T, Head>::value,
Head,
T,
TCompare,
Tail...>::type;
};
//*********************************
// If InsertBefore is true, then T should be inserted before Head
template <typename Head, typename T, template <typename, typename> class TCompare, typename... Tail>
struct insert_sorted_impl<true, Head, T, TCompare, Tail...>
{
using type = etl::type_list<T, Head, Tail...>;
};
//*********************************
// If InsertBefore is false, then T should be inserted after Head, so we recursively call insert_sorted_impl on the tail of the list
template <typename Head, typename T, template <typename, typename> class TCompare, typename... Tail>
struct insert_sorted_impl<false, Head, T, TCompare, Tail...>
{
using type = etl::type_list_push_front_t<typename type_list_insert_sorted_impl<etl::type_list<Tail...>, T, TCompare>::type, Head>;
};
}
//*****************************************************************************
/// Insert T into the correct position in the sorted list, as determined by TCompare
/// Static asserts if TTypeList is not sorted according to TCompare.
/// Comparator must be: template <typename A, typename B> struct Compare : etl::bool_constant<...> {};
//*****************************************************************************
template <typename TTypeList, typename T, template <typename, typename> class TCompare>
struct type_list_insert_sorted : public private_type_list::type_list_insert_sorted_impl<TTypeList, T, TCompare>
{
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
ETL_STATIC_ASSERT((etl::type_list_is_sorted<TTypeList, TCompare>::value), "Cannot insert into a non-sorted type list");
};
#if ETL_USING_CPP11
template <typename TTypeList, typename T, template <typename, typename> class TCompare>
using type_list_insert_sorted_t = typename etl::type_list_insert_sorted<TTypeList, T, TCompare>::type;
#endif
//***************************************************************************
namespace private_type_list
{
//*********************************
// Forward declaration
template <typename TTypeList, template <typename, typename> class TCompare>
struct type_list_sort_impl;
//*********************************
// Empty list
template <template <typename, typename> class TCompare>
struct type_list_sort_impl<etl::type_list<>, TCompare>
{
using type = etl::type_list<>;
};
//*********************************
// Single element list
template <typename T0, template <typename, typename> class TCompare>
struct type_list_sort_impl<etl::type_list<T0>, TCompare>
{
using type = etl::type_list<T0>;
};
//*********************************
// Define a new type_list by sorting the types according to TCompare
template <typename Head, typename... Tail, template <typename, typename> class TCompare>
struct type_list_sort_impl<etl::type_list<Head, Tail...>, TCompare>
{
private:
using sorted_tail = typename type_list_sort_impl<etl::type_list<Tail...>, TCompare>::type;
public:
using type = typename etl::type_list_insert_sorted<sorted_tail, Head, TCompare>::type;
};
}
//*****************************************************************************
/// etl::type_list sorting by a user-supplied type comparator
/// Comparator must be: template <typename A, typename B> struct Compare : etl::bool_constant<...> {};
//*****************************************************************************
template <typename TTypeList, template <typename, typename> class TCompare>
struct type_list_sort : public private_type_list::type_list_sort_impl<TTypeList, TCompare>
{
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
};
#if ETL_USING_CPP11
template <typename TTypeList, template <typename, typename> class TCompare>
using type_list_sort_t = typename etl::type_list_sort<TTypeList, TCompare>::type;
#endif
}
#endif

View File

@ -532,13 +532,13 @@ namespace etl
class integer_sequence
{
public:
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Integral types only");
typedef T value_type;
static ETL_CONSTEXPR size_t size() ETL_NOEXCEPT
{
static ETL_CONSTEXPR size_t size() ETL_NOEXCEPT
{
return sizeof...(Integers);
}
};
@ -559,12 +559,29 @@ namespace etl
{
using type = etl::integer_sequence<size_t, Indices...>;
};
template <size_t Offset, typename IndexSeq>
struct offset_index_sequence;
template <size_t Offset, size_t... Indices>
struct offset_index_sequence<Offset, etl::integer_sequence<size_t, Indices...>>
{
using type = etl::integer_sequence<size_t, (Offset + Indices)...>;
};
}
//***********************************
/// Make an integer sequence.
//***********************************
template <size_t Count>
using make_index_sequence = typename private_integer_sequence::make_index_sequence<Count, etl::integer_sequence<size_t>>::type;
//***********************************
/// Make an integer sequence with an offset.
//***********************************
template <size_t Offset, size_t Count>
using make_index_sequence_with_offset = typename private_integer_sequence::offset_index_sequence<Offset, etl::make_index_sequence<Count>>::type;
//***********************************
// Helper to support both parameter packs and etl::type_list<T...>
// Forward declare etl::type_list to allow use without including type_list.h
@ -587,16 +604,164 @@ namespace etl
};
}
// Accepts either a parameter pack of types or a single etl::type_list<T...>
//***********************************
/// Make an index sequence for a parameter pack of types or an etl::type_list<T...>.
/// Accepts either a parameter pack of types or a single etl::type_list<T...>
//***********************************
template <typename... TTypes>
using make_index_sequence_for = typename private_make_index_sequence_for::impl<TTypes...>::type;
//***********************************
/// An index sequence.
//***********************************
template <size_t... Indices>
using index_sequence = etl::integer_sequence<size_t, Indices...>;
//************************************
/// Alias for make_index_sequence_for.
//************************************
template <typename... TTypes>
using index_sequence_for = typename etl::make_index_sequence_for<TTypes...>;
//************************************
/// Concatenates two index_sequences.
//************************************
template <typename TIndexSequence1, typename TIndexSequence2>
struct index_sequence_cat;
template <size_t... Indices1, size_t... Indices2>
struct index_sequence_cat<etl::index_sequence<Indices1...>, etl::index_sequence<Indices2...>>
{
using type = etl::index_sequence<Indices1..., Indices2...>;
};
template <typename TIndexSequence1, typename TIndexSequence2>
using index_sequence_cat_t = typename index_sequence_cat<TIndexSequence1, TIndexSequence2>::type;
//************************************
/// Pushes an index to the front of an index_sequence.
//************************************
template <typename TIndexSequence, size_t Index>
struct index_sequence_push_front;
template <size_t... Indices, size_t Index>
struct index_sequence_push_front<etl::index_sequence<Indices...>, Index>
{
// Adds the new index to the front of the sequence.
using type = etl::index_sequence<Index, Indices...>;
};
template <typename TIndexSequence, size_t Index>
using index_sequence_push_front_t = typename index_sequence_push_front<TIndexSequence, Index>::type;
//************************************
/// Pop an index from the front of an index_sequence.
//************************************
template <typename TIndexSequence>
struct index_sequence_pop_front;
template <>
struct index_sequence_pop_front<etl::index_sequence<>>
{
using type = etl::index_sequence<>;
};
template <size_t Index, size_t... Indices>
struct index_sequence_pop_front<etl::index_sequence<Index, Indices...>>
{
// Removes the front index by declaring the type to be the tail of the sequence.
using type = etl::index_sequence<Indices...>;
};
template <typename TIndexSequence>
using index_sequence_pop_front_t = typename index_sequence_pop_front<TIndexSequence>::type;
//************************************
/// Pushes an index to the back of an index_sequence.
//************************************
template <typename TIndexSequence, size_t Index>
struct index_sequence_push_back;
template <size_t... Indices, size_t Index>
struct index_sequence_push_back<etl::index_sequence<Indices...>, Index>
{
// Adds the new index to the back of the sequence by concatenating the new index with the sequence.
using type = etl::index_sequence<Indices..., Index>;
};
template <typename TIndexSequence, size_t Index>
using index_sequence_push_back_t = typename index_sequence_push_back<TIndexSequence, Index>::type;
//************************************
/// Pop an index from the back of an index_sequence.
//************************************
template <typename TIndexSequence>
struct index_sequence_pop_back;
// Pop back of and empty sequence is an empty sequence.
template <>
struct index_sequence_pop_back<etl::index_sequence<>>
{
using type = etl::index_sequence<>;
};
// Pop back of a single element sequence is an empty sequence.
// The single element is never added to the result, so is effectively removed.
// This is the terminating specialisation for the general case.
template <size_t Index>
struct index_sequence_pop_back<etl::index_sequence<Index>>
{
using type = etl::index_sequence<>;
};
// Multi element sequence. Pop back is the front element concatenated with the pop back of the tail.
template <size_t Index, size_t... Indices>
struct index_sequence_pop_back<etl::index_sequence<Index, Indices...>>
{
// Removes the last index by concatenating the front index with the pop back of the tail.
// The last index is never added to the result, so is effectively removed.
using type = etl::index_sequence_cat_t<etl::index_sequence<Index>,
typename index_sequence_pop_back<etl::index_sequence<Indices...>>::type>;
};
template <typename TIndexSequence>
using index_sequence_pop_back_t = typename index_sequence_pop_back<TIndexSequence>::type;
//************************************
/// Gets the index at the Nth position in an index_sequence.
//************************************
template <typename TIndexSequence, size_t Nth>
struct index_sequence_at;
template <size_t Nth>
struct index_sequence_at<etl::index_sequence<>, Nth>
{
template <size_t>
struct dependent_false : etl::false_type {};
static_assert(dependent_false<Nth>::value, "Nth out of range for index_sequence_at");
};
// When Nth is 0, the index at the Nth position is the front index of the sequence.
template <size_t Index, size_t... Indices>
struct index_sequence_at<etl::index_sequence<Index, Indices...>, 0>
{
static constexpr size_t value = Index;
};
// When Nth is greater than 0, recurse with the tail of the sequence and Nth - 1.
template <size_t Index, size_t... Indices, size_t Nth>
struct index_sequence_at<etl::index_sequence<Index, Indices...>, Nth>
{
static_assert(Nth < sizeof...(Indices) + 1U, "Nth out of range for index_sequence_at");
static constexpr size_t value = index_sequence_at<etl::index_sequence<Indices...>, Nth - 1U>::value;
};
#if ETL_USING_CPP17
template <typename TIndexSequence, size_t Nth>
inline constexpr size_t index_sequence_at_v = index_sequence_at<TIndexSequence, Nth>::value;
#endif
#endif
//***************************************************************************
@ -634,9 +799,9 @@ namespace etl
//***************************************************************************
/// in_place disambiguation tags.
//***************************************************************************
//*************************
struct in_place_t
struct in_place_t
{
explicit ETL_CONSTEXPR in_place_t() {}
};
@ -644,9 +809,9 @@ namespace etl
#if ETL_USING_CPP17
inline constexpr in_place_t in_place{};
#endif
//*************************
template <typename T> struct in_place_type_t
template <typename T> struct in_place_type_t
{
explicit ETL_CONSTEXPR in_place_type_t() {}
};
@ -657,7 +822,7 @@ namespace etl
#endif
//*************************
template <size_t Index> struct in_place_index_t
template <size_t Index> struct in_place_index_t
{
explicit ETL_CONSTEXPR in_place_index_t() {}
};
@ -750,7 +915,7 @@ namespace etl
// Creates a static member 'call' that calls the specified functor.
//*****************************************************************************
template <auto& Instance>
struct functor_as_static
struct functor_as_static
{
template <typename... TArgs>
static constexpr auto call(TArgs&&... args)
@ -764,7 +929,7 @@ namespace etl
// Creates a static member 'call' that calls the specified member function.
//*****************************************************************************
template <auto Method, auto& Instance>
struct member_function_as_static
struct member_function_as_static
{
template <typename... TArgs>
static constexpr auto call(TArgs&&... args)

View File

@ -35,6 +35,33 @@ SOFTWARE.
namespace
{
#if ETL_USING_CPP11
struct A { static constexpr int id = 0; };
struct B { static constexpr int id = 1; };
struct C { static constexpr int id = 2; };
template <typename T>
struct is_type_a : etl::bool_constant<std::is_same<T, A>::value>
{
};
template <typename T>
struct is_type_b : etl::bool_constant<std::is_same<T, B>::value>
{
};
template <typename T>
struct is_type_c : etl::bool_constant<std::is_same<T, C>::value>
{
};
// Convenience comparator for types that expose a constexpr integral ID (ascending)
template <typename T1, typename T2>
struct by_ascending_id : etl::bool_constant<(T1::id < T2::id)>
{
};
SUITE(test_type_list)
{
//*************************************************************************
@ -196,6 +223,22 @@ namespace
#endif
}
//*************************************************************************
TEST(test_type_list_indices_of_type)
{
using t1 = etl::type_list<char, int, char, uint32_t, char, char>;
using t2 = etl::type_list<>;
using indices1 = etl::type_list_indices_of_type_t<t1, char>;
using expected1 = etl::index_sequence<0U, 2U, 4U, 5U>;
using indices2 = etl::type_list_indices_of_type_t<t2, char>;
using expected2 = etl::index_sequence<>;
CHECK_TRUE((etl::is_same<indices1, expected1>::value));
CHECK_TRUE((etl::is_same<indices2, expected2>::value));
}
//*************************************************************************
TEST(test_type_list_type_at_index)
{
@ -277,6 +320,518 @@ namespace
// Uncomment to generate static_assert error.
//CHECK_FALSE((etl::type_lists_are_convertible_v<t1, t5>));
#endif
}
//*************************************************************************
TEST(test_type_list_sort_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_sort_t<list, by_ascending_id>;
using expected = etl::type_list<>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(0U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_sort_single_list)
{
using list = etl::type_list<A>;
using result = etl::type_list_sort_t<list, by_ascending_id>;
using expected = etl::type_list<A>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(1U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_sort_multiple_list)
{
using list = etl::type_list<B, C, A>;
using result = etl::type_list_sort_t<list, by_ascending_id>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(3U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_is_sorted_for_empty_list)
{
using list = etl::type_list<>;
CHECK((etl::type_list_is_sorted<list, by_ascending_id>::value));
}
//*************************************************************************
TEST(test_type_list_is_sorted_for_single_list)
{
using list = etl::type_list<A>;
CHECK((etl::type_list_is_sorted<list, by_ascending_id>::value));
}
//*************************************************************************
TEST(test_type_list_is_sorted_for_sorted_list)
{
using list = etl::type_list<A, B, C>;
CHECK((etl::type_list_is_sorted<list, by_ascending_id>::value));
}
//*************************************************************************
TEST(test_type_list_is_sorted_for_unsorted_list)
{
using list = etl::type_list<B, C, A>;
CHECK((!etl::type_list_is_sorted<list, by_ascending_id>::value));
}
//*************************************************************************
TEST(test_type_list_insert_sorted_into_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_insert_sorted_t<list, B, by_ascending_id>;
using expected = etl::type_list<B>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(1U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_insert_sorted_before_head)
{
using list = etl::type_list<B, C>;
using result = etl::type_list_insert_sorted_t<list, A, by_ascending_id>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(3U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_insert_sorted_in_middle)
{
using list = etl::type_list<A, C>;
using result = etl::type_list_insert_sorted_t<list, B, by_ascending_id>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(3U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_insert_sorted_at_end)
{
using list = etl::type_list<A, B>;
using result = etl::type_list_insert_sorted_t<list, C, by_ascending_id>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(3U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_push_front_to_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_push_front_t<list, A>;
using expected = etl::type_list<A>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(1U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_push_front_to_non_empty_list)
{
using list = etl::type_list<B, C>;
using result = etl::type_list_push_front_t<list, A>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(3U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_push_back_to_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_push_back_t<list, A>;
using expected = etl::type_list<A>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(1U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_push_back_to_non_empty_list)
{
using list = etl::type_list<A, B>;
using result = etl::type_list_push_back_t<list, C>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(3U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_insert_to_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_insert_t<list, A, 0>;
using expected = etl::type_list<A>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(1U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_insert_to_non_empty_list)
{
using list = etl::type_list<A, B>;
using result1 = etl::type_list_insert_t<list, C, 0>;
using result2 = etl::type_list_insert_t<list, C, 1>;
using result3 = etl::type_list_insert_t<list, C, 2>;
using expected1 = etl::type_list<C, A, B>;
using expected2 = etl::type_list<A, C, B>;
using expected3 = etl::type_list<A, B, C>;
CHECK((etl::is_same<result1, expected1>::value));
CHECK((etl::is_same<result2, expected2>::value));
CHECK((etl::is_same<result3, expected3>::value));
CHECK_EQUAL(3U, etl::type_list_size<result1>::value);
CHECK_EQUAL(3U, etl::type_list_size<result2>::value);
CHECK_EQUAL(3U, etl::type_list_size<result3>::value);
}
//*************************************************************************
TEST(test_type_list_remove_from_empty_list)
{
// Uncomment to generate static_assert error.
//using list = etl::type_list<>;
//using result1 = etl::type_list_remove_t<list, 0>;
}
//*************************************************************************
TEST(test_type_list_remove_from_single_list)
{
using list = etl::type_list<A>;
using result1 = etl::type_list_remove_t<list, 0>;
using expected1 = etl::type_list<>;
CHECK((etl::is_same<result1, expected1>::value));
CHECK_EQUAL(0U, etl::type_list_size<result1>::value);
}
//*************************************************************************
TEST(test_type_list_remove_from_multiple_list)
{
using list = etl::type_list<A, B, C>;
using result1 = etl::type_list_remove_t<list, 0>;
using result2 = etl::type_list_remove_t<list, 1>;
using result3 = etl::type_list_remove_t<list, 2>;
using expected1 = etl::type_list<B, C>;
using expected2 = etl::type_list<A, C>;
using expected3 = etl::type_list<A, B>;
CHECK((etl::is_same<result1, expected1>::value));
CHECK((etl::is_same<result2, expected2>::value));
CHECK((etl::is_same<result3, expected3>::value));
CHECK_EQUAL(2U, etl::type_list_size<result1>::value);
CHECK_EQUAL(2U, etl::type_list_size<result2>::value);
CHECK_EQUAL(2U, etl::type_list_size<result3>::value);
}
//*************************************************************************
TEST(test_type_list_remove_if_from_empty_list)
{
using list = etl::type_list<>;
using result1 = etl::type_list_remove_if_t<list, is_type_b>;
using expected1 = etl::type_list<>;
CHECK((etl::is_same<result1, expected1>::value));
CHECK_EQUAL(0U, etl::type_list_size<result1>::value);
}
//*************************************************************************
TEST(test_type_list_remove_if_from_single_list)
{
using list1 = etl::type_list<A>;
using list2 = etl::type_list<B>;
using result1 = etl::type_list_remove_if_t<list1, is_type_b>;
using result2 = etl::type_list_remove_if_t<list2, is_type_b>;
using expected1 = etl::type_list<A>;
using expected2 = etl::type_list<>;
CHECK((etl::is_same<result1, expected1>::value));
CHECK((etl::is_same<result2, expected2>::value));
CHECK_EQUAL(1U, etl::type_list_size<result1>::value);
CHECK_EQUAL(0U, etl::type_list_size<result2>::value);
}
//*************************************************************************
TEST(test_type_list_remove_if_from_multiple_list)
{
using list = etl::type_list<A, B, C>;
using result1 = etl::type_list_remove_if_t<list, is_type_b>;
using expected1 = etl::type_list<A, C>;
CHECK((etl::is_same<result1, expected1>::value));
CHECK_EQUAL(2U, etl::type_list_size<result1>::value);
}
//*************************************************************************
TEST(test_type_list_pop_front_empty_list)
{
// Uncomment to generate static_assert error.
//using list = etl::type_list<>;
//using result1 = etl::type_list_pop_front_t<list>;
}
//*************************************************************************
TEST(test_type_list_pop_front_from_non_empty_list)
{
using list = etl::type_list<A, B, C>;
using result1 = etl::type_list_pop_front_t<list>;
using result2 = etl::type_list_pop_front_t<result1>;
using result3 = etl::type_list_pop_front_t<result2>;
using expected1 = etl::type_list<B, C>;
using expected2 = etl::type_list<C>;
using expected3 = etl::type_list<>;
CHECK((etl::is_same<result1, expected1>::value));
CHECK((etl::is_same<result2, expected2>::value));
CHECK((etl::is_same<result3, expected3>::value));
CHECK_EQUAL(2U, etl::type_list_size<result1>::value);
CHECK_EQUAL(1U, etl::type_list_size<result2>::value);
CHECK_EQUAL(0U, etl::type_list_size<result3>::value);
}
//*************************************************************************
TEST(test_type_list_pop_back_empty_list)
{
// Uncomment to generate static_assert error.
//using list = etl::type_list<>;
//using result1 = etl::type_list_pop_back_t<list>;
}
//*************************************************************************
TEST(test_type_list_pop_back_from_non_empty_list)
{
using list = etl::type_list<A, B, C>;
using result1 = etl::type_list_pop_back_t<list>;
using result2 = etl::type_list_pop_back_t<result1>;
using result3 = etl::type_list_pop_back_t<result2>;
using expected1 = etl::type_list<A, B>;
using expected2 = etl::type_list<A>;
using expected3 = etl::type_list<>;
CHECK((etl::is_same<result1, expected1>::value));
CHECK((etl::is_same<result2, expected2>::value));
CHECK((etl::is_same<result3, expected3>::value));
CHECK_EQUAL(2U, etl::type_list_size<result1>::value);
CHECK_EQUAL(1U, etl::type_list_size<result2>::value);
CHECK_EQUAL(0U, etl::type_list_size<result3>::value);
}
//*************************************************************************
TEST(test_type_list_unique_for_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_unique_t<list>;
using expected = etl::type_list<>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(0U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_unique_for_non_empty_list)
{
using list = etl::type_list<A, B, A, C, C, B, C>;
using result1 = etl::type_list_unique_t<list>;
using expected1 = etl::type_list<A, B, C>;
CHECK((etl::is_same<result1, expected1>::value));
CHECK_EQUAL(3U, etl::type_list_size<result1>::value);
}
//*************************************************************************
TEST(test_type_list_all_of_for_empty_list)
{
using list1 = etl::type_list<>;
CHECK_TRUE((etl::type_list_all_of<list1, is_type_a>::value));
CHECK_TRUE((etl::type_list_all_of<list1, is_type_b>::value));
CHECK_TRUE((etl::type_list_all_of<list1, is_type_c>::value));
#if ETL_USING_CPP17
CHECK_TRUE((etl::type_list_all_of_v<list1, is_type_a>));
CHECK_TRUE((etl::type_list_all_of_v<list1, is_type_b>));
CHECK_TRUE((etl::type_list_all_of_v<list1, is_type_c>));
#endif
}
//*************************************************************************
TEST(test_type_list_all_of_for_non_empty_list)
{
using list1 = etl::type_list<A, B, C>;
using list2 = etl::type_list<B, B, B>;
CHECK_FALSE((etl::type_list_all_of<list1, is_type_a>::value));
CHECK_FALSE((etl::type_list_all_of<list1, is_type_b>::value));
CHECK_FALSE((etl::type_list_all_of<list1, is_type_c>::value));
CHECK_FALSE((etl::type_list_all_of<list2, is_type_a>::value));
CHECK_TRUE((etl::type_list_all_of<list2, is_type_b>::value));
CHECK_FALSE((etl::type_list_all_of<list2, is_type_c>::value));
#if ETL_USING_CPP17
CHECK_FALSE((etl::type_list_all_of_v<list1, is_type_a>));
CHECK_FALSE((etl::type_list_all_of_v<list1, is_type_b>));
CHECK_FALSE((etl::type_list_all_of_v<list1, is_type_c>));
CHECK_FALSE((etl::type_list_all_of_v<list2, is_type_a>));
CHECK_TRUE((etl::type_list_all_of_v<list2, is_type_b>));
CHECK_FALSE((etl::type_list_all_of_v<list2, is_type_c>));
#endif
}
//*************************************************************************
TEST(test_type_list_any_of_for_empty_list)
{
using list1 = etl::type_list<>;
CHECK_FALSE((etl::type_list_any_of<list1, is_type_a>::value));
CHECK_FALSE((etl::type_list_any_of<list1, is_type_b>::value));
CHECK_FALSE((etl::type_list_any_of<list1, is_type_c>::value));
#if ETL_USING_CPP17
CHECK_FALSE((etl::type_list_any_of_v<list1, is_type_a>));
CHECK_FALSE((etl::type_list_any_of_v<list1, is_type_b>));
CHECK_FALSE((etl::type_list_any_of_v<list1, is_type_c>));
#endif
}
//*************************************************************************
TEST(test_type_list_any_of_for_non_empty_list)
{
using list1 = etl::type_list<A, B, C>;
using list2 = etl::type_list<B, B, B>;
CHECK_TRUE((etl::type_list_any_of<list1, is_type_a>::value));
CHECK_TRUE((etl::type_list_any_of<list1, is_type_b>::value));
CHECK_TRUE((etl::type_list_any_of<list1, is_type_c>::value));
CHECK_FALSE((etl::type_list_any_of<list2, is_type_a>::value));
CHECK_TRUE((etl::type_list_any_of<list2, is_type_b>::value));
CHECK_FALSE((etl::type_list_any_of<list2, is_type_c>::value));
#if ETL_USING_CPP17
CHECK_TRUE((etl::type_list_any_of_v<list1, is_type_a>));
CHECK_TRUE((etl::type_list_any_of_v<list1, is_type_b>));
CHECK_TRUE((etl::type_list_any_of_v<list1, is_type_c>));
CHECK_FALSE((etl::type_list_any_of_v<list2, is_type_a>));
CHECK_TRUE((etl::type_list_any_of_v<list2, is_type_b>));
CHECK_FALSE((etl::type_list_any_of_v<list2, is_type_c>));
#endif
}
//*************************************************************************
TEST(test_type_list_none_of_for_empty_list)
{
using list1 = etl::type_list<>;
CHECK_TRUE((etl::type_list_none_of<list1, is_type_a>::value));
CHECK_TRUE((etl::type_list_none_of<list1, is_type_b>::value));
CHECK_TRUE((etl::type_list_none_of<list1, is_type_c>::value));
#if ETL_USING_CPP17
CHECK_TRUE((etl::type_list_none_of_v<list1, is_type_a>));
CHECK_TRUE((etl::type_list_none_of_v<list1, is_type_b>));
CHECK_TRUE((etl::type_list_none_of_v<list1, is_type_c>));
#endif
}
//*************************************************************************
TEST(test_type_list_none_of_for_non_empty_list)
{
using list1 = etl::type_list<A, B, C>;
using list2 = etl::type_list<B, B, B>;
CHECK_FALSE((etl::type_list_none_of<list1, is_type_a>::value));
CHECK_FALSE((etl::type_list_none_of<list1, is_type_b>::value));
CHECK_FALSE((etl::type_list_none_of<list1, is_type_c>::value));
CHECK_TRUE((etl::type_list_none_of<list2, is_type_a>::value));
CHECK_FALSE((etl::type_list_none_of<list2, is_type_b>::value));
CHECK_TRUE((etl::type_list_none_of<list2, is_type_c>::value));
#if ETL_USING_CPP17
CHECK_FALSE((etl::type_list_none_of_v<list1, is_type_a>));
CHECK_FALSE((etl::type_list_none_of_v<list1, is_type_b>));
CHECK_FALSE((etl::type_list_none_of_v<list1, is_type_c>));
CHECK_TRUE((etl::type_list_none_of_v<list2, is_type_a>));
CHECK_FALSE((etl::type_list_none_of_v<list2, is_type_b>));
CHECK_TRUE((etl::type_list_none_of_v<list2, is_type_c>));
#endif
}
//*************************************************************************
TEST(test_type_list_is_unique_for_empty_list)
{
using list1 = etl::type_list<>;
CHECK_TRUE((etl::type_list_is_unique<list1>::value));
#if ETL_USING_CPP17
CHECK_TRUE((etl::type_list_is_unique_v<list1>));
#endif
}
//*************************************************************************
TEST(test_type_list_is_unique_for_non_empty_list)
{
using list1 = etl::type_list<A, B, C>;
using list2 = etl::type_list<A, B, A>;
CHECK_TRUE((etl::type_list_is_unique<list1>::value));
CHECK_FALSE((etl::type_list_is_unique<list2>::value));
#if ETL_USING_CPP17
CHECK_TRUE((etl::type_list_is_unique_v<list1>));
CHECK_FALSE((etl::type_list_is_unique_v<list2>));
#endif
}
//*************************************************************************
TEST(test_type_list_is_empty)
{
using list1 = etl::type_list<>;
using list2 = etl::type_list<A>;
CHECK_TRUE((etl::type_list_is_empty<list1>::value));
CHECK_FALSE((etl::type_list_is_empty<list2>::value));
#if ETL_USING_CPP17
CHECK_TRUE((etl::type_list_is_empty_v<list1>));
CHECK_FALSE((etl::type_list_is_empty_v<list2>));
#endif
}
}

View File

@ -864,6 +864,21 @@ namespace
}
#endif
//*********************************
TEST(test_make_index_sequence_matches_expected)
{
using seq0 = etl::make_index_sequence<0U>;
using seq1 = etl::make_index_sequence<1U>;
using seq4 = etl::make_index_sequence<4U>;
using expect0 = etl::index_sequence<>;
using expect1 = etl::index_sequence<0U>;
using expect4 = etl::index_sequence<0U, 1U, 2U, 3U>;
CHECK_TRUE((std::is_same<seq0, expect0>::value));
CHECK_TRUE((std::is_same<seq1, expect1>::value));
CHECK_TRUE((std::is_same<seq4, expect4>::value));
}
//*********************************
TEST(test_make_index_sequence_for_pack_matches_expected)
{
@ -897,5 +912,122 @@ namespace
CHECK_TRUE((std::is_same<seq12, expect12>::value));
CHECK_TRUE((std::is_same<seq123, expect123>::value));
}
//*********************************
TEST(test_make_index_sequence_with_offset_matches_expected)
{
using seq0 = etl::make_index_sequence_with_offset<5U, 0U>;
using seq2 = etl::make_index_sequence_with_offset<3U, 2U>;
using seq4 = etl::make_index_sequence_with_offset<7U, 4U>;
using expect0 = etl::index_sequence<>;
using expect2 = etl::index_sequence<3U, 4U>;
using expect4 = etl::index_sequence<7U, 8U, 9U, 10U>;
CHECK_TRUE((std::is_same<seq0, expect0>::value));
CHECK_TRUE((std::is_same<seq2, expect2>::value));
CHECK_TRUE((std::is_same<seq4, expect4>::value));
}
//*********************************
TEST(test_index_sequence_push_front_matches_expected)
{
using seq0 = etl::index_sequence<>;
using seq1 = etl::index_sequence<1U, 2U>;
using result0 = etl::index_sequence_push_front_t<seq0, 5U>;
using result1 = etl::index_sequence_push_front_t<seq1, 0U>;
using expect0 = etl::index_sequence<5U>;
using expect1 = etl::index_sequence<0U, 1U, 2U>;
CHECK_TRUE((std::is_same<result0, expect0>::value));
CHECK_TRUE((std::is_same<result1, expect1>::value));
}
//*********************************
TEST(test_index_sequence_pop_front_matches_expected)
{
using seq0 = etl::index_sequence<>;
using seq1 = etl::index_sequence<1U, 2U>;
using result0 = etl::index_sequence_pop_front_t<seq0>;
using result1 = etl::index_sequence_pop_front_t<seq1>;
using expect0 = etl::index_sequence<>;
using expect1 = etl::index_sequence<2U>;
CHECK_TRUE((std::is_same<result0, expect0>::value));
CHECK_TRUE((std::is_same<result1, expect1>::value));
}
//*********************************
TEST(test_index_sequence_push_back_matches_expected)
{
using seq0 = etl::index_sequence<>;
using seq1 = etl::index_sequence<1U, 2U>;
using result0 = etl::index_sequence_push_back_t<seq0, 5U>;
using result1 = etl::index_sequence_push_back_t<seq1, 3U>;
using expect0 = etl::index_sequence<5U>;
using expect1 = etl::index_sequence<1U, 2U, 3U>;
CHECK_TRUE((std::is_same<result0, expect0>::value));
CHECK_TRUE((std::is_same<result1, expect1>::value));
}
//*********************************
TEST(test_index_sequence_pop_back_matches_expected)
{
using seq0 = etl::index_sequence<>;
using seq1 = etl::index_sequence<1U, 2U>;
using result0 = etl::index_sequence_pop_back_t<seq0>;
using result1 = etl::index_sequence_pop_back_t<seq1>;
using expect0 = etl::index_sequence<>;
using expect1 = etl::index_sequence<1U>;
CHECK_TRUE((std::is_same<result0, expect0>::value));
CHECK_TRUE((std::is_same<result1, expect1>::value));
}
//*********************************
TEST(test_index_sequence_cat_matches_expected)
{
using seq0 = etl::index_sequence<>;
using seq1 = etl::index_sequence<0U, 1U>;
using seq2 = etl::index_sequence<2U, 3U>;
using result0 = etl::index_sequence_cat_t<seq0, seq1>;
using result1 = etl::index_sequence_cat_t<seq1, seq2>;
using expect0 = etl::index_sequence<0U, 1U>;
using expect1 = etl::index_sequence<0U, 1U, 2U, 3U>;
CHECK_TRUE((std::is_same<result0, expect0>::value));
CHECK_TRUE((std::is_same<result1, expect1>::value));
}
//*********************************
TEST(test_index_sequence_at_matches_expected)
{
// using seq0 = etl::index_sequence<>; // This should fail to compile as seq0 is empty
using seq1 = etl::index_sequence<1U, 2U, 3U>;
//using result0 = etl::index_sequence_at<seq0, 0>; // This should fail to compile as seq0 is empty
//auto ignore0 = result0; // Uses result0
size_t result1a = etl::index_sequence_at<seq1, 0>::value;
size_t result1b = etl::index_sequence_at<seq1, 1>::value;
size_t result1c = etl::index_sequence_at<seq1, 2>::value;
//size_t result1d = etl::index_sequence_at<seq1, 3>::value; // This should fail to compile as seq1 only has 3 elements
//auto ignore1d = result1d; // Uses result1d
size_t expect1a = 1U;
size_t expect1b = 2U;
size_t expect1c = 3U;
CHECK_EQUAL(expect1a, result1a);
CHECK_EQUAL(expect1b, result1b);
CHECK_EQUAL(expect1c, result1c);
#if ETL_USING_CPP17
size_t result1e = etl::index_sequence_at_v<seq1, 0>;
size_t result1f = etl::index_sequence_at_v<seq1, 1>;
size_t result1g = etl::index_sequence_at_v<seq1, 2>;
CHECK_EQUAL(expect1a, result1e);
CHECK_EQUAL(expect1b, result1f);
CHECK_EQUAL(expect1c, result1g);
#endif
}
}
}