mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Merge branch 'development' into refactor/reduce-string-flash-usage
This commit is contained in:
commit
c1a9c09419
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user