mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Added etl::type_list_all_of, etl::type_list_any_of, and etl::type_list_none_of
This commit is contained in:
parent
dc0f62cc3f
commit
25b88e509b
@ -183,7 +183,7 @@ namespace etl
|
||||
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_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
|
||||
@ -606,6 +606,78 @@ namespace etl
|
||||
using type_list_unique_t = typename etl::type_list_unique<TTypeList>::type;
|
||||
#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<false>
|
||||
{
|
||||
};
|
||||
|
||||
#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.
|
||||
@ -616,15 +688,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");
|
||||
@ -686,7 +758,7 @@ namespace etl
|
||||
|
||||
//*****************************************************************************
|
||||
namespace private_type_list
|
||||
{
|
||||
{
|
||||
//*********************************
|
||||
template <bool InsertBefore, typename Head, typename T, template <typename, typename> class TCompare, typename... Tail>
|
||||
struct insert_sorted_impl;
|
||||
|
||||
@ -36,18 +36,29 @@ 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_asencding_id : etl::bool_constant<(T1::id < T2::id)>
|
||||
struct by_ascencding_id : etl::bool_constant<(T1::id < T2::id)>
|
||||
{
|
||||
};
|
||||
|
||||
@ -300,7 +311,7 @@ namespace
|
||||
TEST(test_type_list_sort_empty_list)
|
||||
{
|
||||
using list = etl::type_list<>;
|
||||
using result = etl::type_list_sort_t<list, by_asencding_id>;
|
||||
using result = etl::type_list_sort_t<list, by_ascencding_id>;
|
||||
using expected = etl::type_list<>;
|
||||
|
||||
CHECK((etl::is_same<result, expected>::value));
|
||||
@ -311,7 +322,7 @@ namespace
|
||||
TEST(test_type_list_sort_single_list)
|
||||
{
|
||||
using list = etl::type_list<A>;
|
||||
using result = etl::type_list_sort_t<list, by_asencding_id>;
|
||||
using result = etl::type_list_sort_t<list, by_ascencding_id>;
|
||||
using expected = etl::type_list<A>;
|
||||
|
||||
CHECK((etl::is_same<result, expected>::value));
|
||||
@ -322,7 +333,7 @@ namespace
|
||||
TEST(test_type_list_sort_multiple_list)
|
||||
{
|
||||
using list = etl::type_list<B, C, A>;
|
||||
using result = etl::type_list_sort_t<list, by_asencding_id>;
|
||||
using result = etl::type_list_sort_t<list, by_ascencding_id>;
|
||||
using expected = etl::type_list<A, B, C>;
|
||||
|
||||
CHECK((etl::is_same<result, expected>::value));
|
||||
@ -398,7 +409,7 @@ namespace
|
||||
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);
|
||||
@ -490,7 +501,7 @@ namespace
|
||||
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>;
|
||||
}
|
||||
@ -566,6 +577,129 @@ namespace
|
||||
|
||||
CHECK_EQUAL(3U, etl::type_list_size<result1>::value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_type_list_all_of_for_empty_list)
|
||||
{
|
||||
using list1 = etl::type_list<>;
|
||||
|
||||
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));
|
||||
|
||||
#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>));
|
||||
#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
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user