Commit e7c9dcf5 authored by Matthias Vallentin's avatar Matthias Vallentin

Refactor type list implementation

New suffixes *_t offer C++14-like semantics for type manipulation. Once
we support C++14 compilers, we can also uncomment the corresponding *_v
variable templates.
parent d754f1c6
...@@ -54,6 +54,10 @@ struct is_type_list<type_list<Ts...>> { ...@@ -54,6 +54,10 @@ struct is_type_list<type_list<Ts...>> {
static constexpr bool value = true; static constexpr bool value = true;
}; };
// Uncomment after having switched to C++14
//template <class T>
//inline constexpr bool is_type_list_v = is_type_list<T>::value;
// T head(type_list) // T head(type_list)
/// Gets the first element of `List`. /// Gets the first element of `List`.
...@@ -89,6 +93,9 @@ struct tl_tail<type_list<T0, Ts...>> { ...@@ -89,6 +93,9 @@ struct tl_tail<type_list<T0, Ts...>> {
using type = type_list<Ts...>; using type = type_list<Ts...>;
}; };
template <class List>
using tl_tail_t = typename tl_tail<List>::type;
// size_t size(type_list) // size_t size(type_list)
/// Gets the number of template parameters of `List`. /// Gets the number of template parameters of `List`.
...@@ -103,6 +110,10 @@ struct tl_size<type_list<Ts...>> { ...@@ -103,6 +110,10 @@ struct tl_size<type_list<Ts...>> {
template <class... Ts> template <class... Ts>
constexpr size_t tl_size<type_list<Ts...>>::value; constexpr size_t tl_size<type_list<Ts...>>::value;
// Uncomment after having switched to C++14
//template <class List>
//inline constexpr size_t tl_size_v = tl_size<List>::value;
// T back(type_list) // T back(type_list)
/// Gets the last element in `List`. /// Gets the last element in `List`.
...@@ -126,6 +137,9 @@ struct tl_back<type_list<T0, T1, Ts...>> { ...@@ -126,6 +137,9 @@ struct tl_back<type_list<T0, T1, Ts...>> {
using type = typename tl_back<type_list<T1, Ts...>>::type; using type = typename tl_back<type_list<T1, Ts...>>::type;
}; };
template <class List>
using tl_back_t = typename tl_back<List>::type;
// bool empty(type_list) // bool empty(type_list)
/// Tests whether a list is empty. /// Tests whether a list is empty.
...@@ -134,6 +148,10 @@ struct tl_empty { ...@@ -134,6 +148,10 @@ struct tl_empty {
static constexpr bool value = std::is_same<empty_type_list, List>::value; static constexpr bool value = std::is_same<empty_type_list, List>::value;
}; };
// Uncomment after having switched to C++14
//template <class List>
//inline constexpr bool tl_empty_v = tl_empty<List>::value;
// list slice(size_t, size_t) // list slice(size_t, size_t)
template <size_t LeftOffset, template <size_t LeftOffset,
...@@ -147,7 +165,7 @@ struct tl_slice_impl { ...@@ -147,7 +165,7 @@ struct tl_slice_impl {
LeftOffset - 1, LeftOffset - 1,
Remaining, Remaining,
PadType, PadType,
typename tl_tail<List>::type, tl_tail_t<List>,
Ts... Ts...
>::type; >::type;
}; };
...@@ -159,9 +177,9 @@ struct tl_slice_impl<0, Remaining, PadType, List, Ts...> { ...@@ -159,9 +177,9 @@ struct tl_slice_impl<0, Remaining, PadType, List, Ts...> {
0, 0,
Remaining - 1, Remaining - 1,
PadType, PadType,
typename tl_tail<List>::type, tl_tail_t<List>,
Ts..., Ts...,
typename tl_head<List>::type tl_head_t<List>
>::type; >::type;
}; };
...@@ -217,11 +235,14 @@ struct tl_slice { ...@@ -217,11 +235,14 @@ struct tl_slice {
>::type; >::type;
}; };
template <class List, size_t First, size_t Last>
using tl_slice_t = typename tl_slice<List, First, Last>::type;
/// Creates a new list containing the last `N` elements. /// Creates a new list containing the last `N` elements.
template <class List, size_t NewSize, size_t OldSize = tl_size<List>::value> template <class List, size_t NewSize, size_t OldSize = tl_size<List>::value>
struct tl_right { struct tl_right {
static constexpr size_t first_idx = OldSize > NewSize ? OldSize - NewSize : 0; static constexpr size_t first_idx = OldSize > NewSize ? OldSize - NewSize : 0;
using type = typename tl_slice<List, first_idx, OldSize>::type; using type = tl_slice_t<List, first_idx, OldSize>;
}; };
template <class List, size_t N> template <class List, size_t N>
...@@ -239,6 +260,9 @@ struct tl_right<empty_type_list, 0, 0> { ...@@ -239,6 +260,9 @@ struct tl_right<empty_type_list, 0, 0> {
using type = empty_type_list; using type = empty_type_list;
}; };
template <class List, size_t NewSize, size_t OldSize = tl_size<List>::value>
using tl_right_t = typename tl_right<List, NewSize, OldSize>::type;
template <class ListA, class ListB, template <class ListA, class ListB,
template <class, typename> class Fun = to_type_pair> template <class, typename> class Fun = to_type_pair>
struct tl_zip_impl; struct tl_zip_impl;
...@@ -263,23 +287,29 @@ struct tl_zip { ...@@ -263,23 +287,29 @@ struct tl_zip {
static constexpr size_t result_size = (sizea < sizeb) ? sizea : sizeb; static constexpr size_t result_size = (sizea < sizeb) ? sizea : sizeb;
using type = using type =
typename tl_zip_impl< typename tl_zip_impl<
typename tl_slice<ListA, 0, result_size>::type, tl_slice_t<ListA, 0, result_size>,
typename tl_slice<ListB, 0, result_size>::type, tl_slice_t<ListB, 0, result_size>,
Fun Fun
>::type; >::type;
}; };
template <class ListA, class ListB, template <class, class> class Fun>
using tl_zip_t = typename tl_zip<ListA, ListB, Fun>::type;
/// Equal to `zip(right(ListA, N), right(ListB, N), Fun)`. /// Equal to `zip(right(ListA, N), right(ListB, N), Fun)`.
template <class ListA, class ListB, template <class, class> class Fun, size_t N> template <class ListA, class ListB, template <class, class> class Fun, size_t N>
struct tl_zip_right { struct tl_zip_right {
using type = using type =
typename tl_zip_impl< typename tl_zip_impl<
typename tl_right<ListA, N>::type, tl_right_t<ListA, N>,
typename tl_right<ListB, N>::type, tl_right_t<ListB, N>,
Fun Fun
>::type; >::type;
}; };
template <class ListA, class ListB, template <class, class> class Fun, size_t N>
using tl_zip_right_t = typename tl_zip_right<ListA, ListB, Fun, N>::type;
template <class ListA, class ListB, template <class ListA, class ListB,
typename PadA = unit_t, typename PadB = unit_t, typename PadA = unit_t, typename PadB = unit_t,
template <class, typename> class Fun = to_type_pair> template <class, typename> class Fun = to_type_pair>
...@@ -295,6 +325,11 @@ struct tl_zip_all { ...@@ -295,6 +325,11 @@ struct tl_zip_all {
>::type; >::type;
}; };
template <class ListA, class ListB,
typename PadA = unit_t, typename PadB = unit_t,
template <class, typename> class Fun = to_type_pair>
using tl_zip_all_t = typename tl_zip_all<ListA, ListB, PadA, PadB, Fun>::type;
template <class ListA> template <class ListA>
struct tl_unzip; struct tl_unzip;
...@@ -334,6 +369,10 @@ struct tl_index_of<type_list<Ts...>, T> { ...@@ -334,6 +369,10 @@ struct tl_index_of<type_list<Ts...>, T> {
static constexpr int value = tl_index_of_impl<0, T, Ts...>::value; static constexpr int value = tl_index_of_impl<0, T, Ts...>::value;
}; };
// Uncomment after having switched to C++14
//template <class List, class T>
//inline constexpr int tl_index_of_v = tl_index_of<List, T>::value;
// int index_of(list, predicate) // int index_of(list, predicate)
template <int Pos, template <class> class Pred, class... Ts> template <int Pos, template <class> class Pred, class... Ts>
...@@ -359,6 +398,10 @@ struct tl_index_where<type_list<Ts...>, Pred> { ...@@ -359,6 +398,10 @@ struct tl_index_where<type_list<Ts...>, Pred> {
static constexpr int value = tl_index_where_impl<0, Pred, Ts...>::value; static constexpr int value = tl_index_where_impl<0, Pred, Ts...>::value;
}; };
// Uncomment after having switched to C++14
//template <class List, template <class> class Pred>
//inline constexpr int tl_index_where_v = tl_index_where<List, Pred>::value;
// list reverse() // list reverse()
template <class From, class... Elements> template <class From, class... Elements>
...@@ -380,6 +423,9 @@ struct tl_reverse { ...@@ -380,6 +423,9 @@ struct tl_reverse {
using type = typename tl_reverse_impl<List>::type; using type = typename tl_reverse_impl<List>::type;
}; };
template <class List>
using tl_reverse_t = typename tl_reverse<List>::type;
// type find(list, predicate) // type find(list, predicate)
/// Finds the first element of type `What` beginning at index `Pos`. /// Finds the first element of type `What` beginning at index `Pos`.
...@@ -419,8 +465,8 @@ using tl_find_t = typename tl_find<List, Pred>::type; ...@@ -419,8 +465,8 @@ using tl_find_t = typename tl_find<List, Pred>::type;
template <class List, template <class> class Pred> template <class List, template <class> class Pred>
struct tl_forall { struct tl_forall {
static constexpr bool value = static constexpr bool value =
Pred<typename tl_head<List>::type>::value Pred<tl_head_t<List>>::value
&& tl_forall<typename tl_tail<List>::type, Pred>::value; && tl_forall<tl_tail_t<List>, Pred>::value;
}; };
template <template <class> class Pred> template <template <class> class Pred>
...@@ -428,13 +474,15 @@ struct tl_forall<empty_type_list, Pred> { ...@@ -428,13 +474,15 @@ struct tl_forall<empty_type_list, Pred> {
static constexpr bool value = true; static constexpr bool value = true;
}; };
// Uncomment after having switched to C++14
//template <class List, template <class> class Pred>
//inline constexpr bool tl_forall_v = tl_forall<List, Pred>::value;
template <class ListA, class ListB, template <class, class> class Pred> template <class ListA, class ListB, template <class, class> class Pred>
struct tl_forall2_impl { struct tl_forall2_impl {
static constexpr bool value = static constexpr bool value =
Pred<typename tl_head<ListA>::type, Pred<tl_head_t<ListA>, tl_head_t<ListB>>::value
typename tl_head<ListB>::type>::value && tl_forall2_impl<tl_tail_t<ListA>, tl_tail_t<ListB>, Pred>::value;
&& tl_forall2_impl<typename tl_tail<ListA>::type,
typename tl_tail<ListB>::type, Pred>::value;
}; };
template <template <class, typename> class Pred> template <template <class, typename> class Pred>
...@@ -451,19 +499,21 @@ struct tl_binary_forall { ...@@ -451,19 +499,21 @@ struct tl_binary_forall {
&& tl_forall2_impl<ListA, ListB, Pred>::value; && tl_forall2_impl<ListA, ListB, Pred>::value;
}; };
// Uncomment after having switched to C++14
//template <class ListA, class ListB, template <class, class> class Pred>
//inline constexpr bool tl_binary_forall_v
// = tl_binary_forall<ListA, ListB, Pred>::value;
/// Tests whether a predicate holds for some of the elements of a list. /// Tests whether a predicate holds for some of the elements of a list.
template <class List, template <class> class Pred> template <class List, template <class> class Pred>
struct tl_exists { struct tl_exists {
static constexpr bool value = static constexpr bool value =
Pred<typename tl_head<List>::type>::value Pred<tl_head_t<List>>::value || tl_exists<tl_tail_t<List>, Pred>::value;
|| tl_exists<typename tl_tail<List>::type, Pred>::value;
}; };
template <template <class> class Pred> // Uncomment after having switched to C++14
struct tl_exists<empty_type_list, Pred> { //template <class List, template <class> class Pred>
static constexpr bool value = false; //inline constexpr bool tl_exists_v = tl_exists<List, Pred>::value;
};
// size_t count(predicate) // size_t count(predicate)
...@@ -471,8 +521,8 @@ struct tl_exists<empty_type_list, Pred> { ...@@ -471,8 +521,8 @@ struct tl_exists<empty_type_list, Pred> {
template <class List, template <class> class Pred> template <class List, template <class> class Pred>
struct tl_count { struct tl_count {
static constexpr size_t value = static constexpr size_t value =
(Pred<typename tl_head<List>::type>::value ? 1 : 0) (Pred<tl_head_t<List>>::value ? 1 : 0)
+ tl_count<typename tl_tail<List>::type, Pred>::value; + tl_count<tl_tail_t<List>, Pred>::value;
}; };
template <template <class> class Pred> template <template <class> class Pred>
...@@ -483,14 +533,18 @@ struct tl_count<empty_type_list, Pred> { ...@@ -483,14 +533,18 @@ struct tl_count<empty_type_list, Pred> {
template <class List, template <class> class Pred> template <class List, template <class> class Pred>
constexpr size_t tl_count<List, Pred>::value; constexpr size_t tl_count<List, Pred>::value;
// Uncomment after having switched to C++14
//template <class List, template <class> class Pred>
//inline constexpr size_t tl_count_v = tl_count<List, Pred>::value;
// size_t count(type) // size_t count(type)
/// Counts the number of elements in the list which are equal to `T`. /// Counts the number of elements in the list which are equal to `T`.
template <class List, class T> template <class List, class T>
struct tl_count_type { struct tl_count_type {
static constexpr size_t value = static constexpr size_t value =
(std::is_same<typename tl_head<List>::type, T>::value ? 1 : 0) (std::is_same<tl_head_t<List>, T>::value ? 1 : 0)
+ tl_count_type<typename tl_tail<List>::type, T>::value; + tl_count_type<tl_tail_t<List>, T>::value;
}; };
template <class T> template <class T>
...@@ -501,23 +555,30 @@ struct tl_count_type<empty_type_list, T> { ...@@ -501,23 +555,30 @@ struct tl_count_type<empty_type_list, T> {
template <class List, class T> template <class List, class T>
constexpr size_t tl_count_type<List, T>::value; constexpr size_t tl_count_type<List, T>::value;
// Uncomment after having switched to C++14
//template <class List, class T>
//inline constexpr size_t tl_count_type_v = tl_count_type<List, T>::value;
// size_t count_not(predicate) // size_t count_not(predicate)
/// Counts the number of elements in the list which satisfy a predicate. /// Counts the number of elements in the list which satisfy a predicate.
template <class List, template <class> class Pred> template <class List, template <class> class Pred>
struct tl_count_not { struct tl_count_not {
static constexpr size_t value = static constexpr size_t value =
(Pred<typename tl_head<List>::type>::value ? 0 : 1) + (Pred<tl_head_t<List>>::value ? 0 : 1) +
tl_count_not<typename tl_tail<List>::type, Pred>::value; tl_count_not<tl_tail_t<List>, Pred>::value;
}; };
template <template <class> class Pred> template <template <class> class Pred>
struct tl_count_not<empty_type_list, Pred> { struct tl_count_not<empty_type_list, Pred> {
static constexpr size_t value = 0; static constexpr size_t value = 0;
}; };
// Uncomment after having switched to C++14
//template <class List, template <class> class Pred>
//inline constexpr size_t tl_count_not_v = tl_count_not<List, Pred>::value;
template <class ListA, class ListB> template <class ListA, class ListB>
struct tl_concat_impl; struct tl_concat_impl;
...@@ -547,6 +608,9 @@ struct tl_concat<List0, List1, Lists...> { ...@@ -547,6 +608,9 @@ struct tl_concat<List0, List1, Lists...> {
>::type; >::type;
}; };
template <class... Lists>
using tl_concat_t = typename tl_concat<Lists...>::type;
// list push_back(list, type) // list push_back(list, type)
template <class List, class What> template <class List, class What>
...@@ -556,9 +620,11 @@ struct tl_push_back; ...@@ -556,9 +620,11 @@ struct tl_push_back;
template <class... ListTs, class What> template <class... ListTs, class What>
struct tl_push_back<type_list<ListTs...>, What> { struct tl_push_back<type_list<ListTs...>, What> {
using type = type_list<ListTs..., What>; using type = type_list<ListTs..., What>;
}; };
template <class List, class What>
using tl_push_back_t = typename tl_push_back<List, What>::type;
template <class List, class What> template <class List, class What>
struct tl_push_front; struct tl_push_front;
...@@ -568,12 +634,18 @@ struct tl_push_front<type_list<ListTs...>, What> { ...@@ -568,12 +634,18 @@ struct tl_push_front<type_list<ListTs...>, What> {
using type = type_list<What, ListTs...>; using type = type_list<What, ListTs...>;
}; };
template <class List, class What>
using tl_push_front_t = typename tl_push_front<List, What>::type;
/// Alias for `tl_push_front<List, What>`. /// Alias for `tl_push_front<List, What>`.
template <class What, class List> template <class What, class List>
struct tl_cons : tl_push_front<List, What> { struct tl_cons : tl_push_front<List, What> {
// nop // nop
}; };
template <class List, class What>
using tl_cons_t = tl_push_front_t<List, What>;
// list map(list, trait) // list map(list, trait)
template <class T, template <class> class... Funs> template <class T, template <class> class... Funs>
...@@ -589,13 +661,16 @@ struct tl_apply_all<T, Fun0, Funs...> { ...@@ -589,13 +661,16 @@ struct tl_apply_all<T, Fun0, Funs...> {
using type = typename tl_apply_all<typename Fun0<T>::type, Funs...>::type; using type = typename tl_apply_all<typename Fun0<T>::type, Funs...>::type;
}; };
template <class T, template <class> class... Funs>
using tl_apply_all_t = typename tl_apply_all<T, Funs...>::type;
/// Creates a new list by applying a "template function" to each element. /// Creates a new list by applying a "template function" to each element.
template <class List, template <class> class... Funs> template <class List, template <class> class... Funs>
struct tl_map; struct tl_map;
template <class... Ts, template <class> class... Funs> template <class... Ts, template <class> class... Funs>
struct tl_map<type_list<Ts...>, Funs...> { struct tl_map<type_list<Ts...>, Funs...> {
using type = type_list<typename tl_apply_all<Ts, Funs...>::type...>; using type = type_list<tl_apply_all_t<Ts, Funs...>...>;
}; };
template <class List, template <class> class... Funs> template <class List, template <class> class... Funs>
...@@ -607,19 +682,16 @@ template <class List, template <class> class Trait, bool TRes, ...@@ -607,19 +682,16 @@ template <class List, template <class> class Trait, bool TRes,
template <class> class... Funs> template <class> class... Funs>
struct tl_map_conditional { struct tl_map_conditional {
using type = using type =
typename tl_concat< tl_concat_t<
type_list< type_list<
typename std::conditional< typename std::conditional<
Trait<typename tl_head<List>::type>::value == TRes, Trait<tl_head_t<List>>::value == TRes,
typename tl_apply_all<typename tl_head<List>::type, Funs...>::type, tl_apply_all_t<tl_head_t<List>, Funs...>,
typename tl_head<List>::type tl_head_t<List>
>::type >::type
>, >,
typename tl_map_conditional< typename tl_map_conditional<tl_tail_t<List>, Trait, TRes, Funs...>::type
typename tl_tail<List>::type, >;
Trait, TRes, Funs...
>::type
>::type;
}; };
template <template <class> class Trait, bool TraitResult, template <template <class> class Trait, bool TraitResult,
...@@ -641,6 +713,9 @@ struct tl_pop_back<empty_type_list> { ...@@ -641,6 +713,9 @@ struct tl_pop_back<empty_type_list> {
using type = empty_type_list; using type = empty_type_list;
}; };
template <class List>
using tl_pop_back_t = typename tl_pop_back<List>::type;
// list replace_back() // list replace_back()
/// Creates a new list with all but the last element of `List` /// Creates a new list with all but the last element of `List`
...@@ -657,6 +732,10 @@ struct tl_replace_back<type_list<T>, Back, type_list<Us...>> { ...@@ -657,6 +732,10 @@ struct tl_replace_back<type_list<T>, Back, type_list<Us...>> {
using type = type_list<Us..., Back>; using type = type_list<Us..., Back>;
}; };
template <class List, class Back, class Intermediate = type_list<>>
using tl_replace_back_t
= typename tl_replace_back<List, Back, Intermediate>::type;
// type at(size_t) // type at(size_t)
template <size_t N, class... E> template <size_t N, class... E>
...@@ -686,6 +765,9 @@ struct tl_at<type_list<E...>, N> { ...@@ -686,6 +765,9 @@ struct tl_at<type_list<E...>, N> {
using type = typename tl_at_impl<N, E...>::type; using type = typename tl_at_impl<N, E...>::type;
}; };
template <class List, size_t N>
using tl_at_t = typename tl_at<List, N>::type;
// list prepend(type) // list prepend(type)
template <class List, class What> template <class List, class What>
...@@ -697,6 +779,9 @@ struct tl_prepend<type_list<T...>, What> { ...@@ -697,6 +779,9 @@ struct tl_prepend<type_list<T...>, What> {
using type = type_list<What, T...>; using type = type_list<What, T...>;
}; };
template <class List, class What>
using tl_prepend_t = typename tl_prepend<List, What>::type;
// list filter(predicate) // list filter(predicate)
// list filter_not(predicate) // list filter_not(predicate)
...@@ -716,13 +801,13 @@ struct tl_filter_impl<type_list<T0, T...>, false, S...> { ...@@ -716,13 +801,13 @@ struct tl_filter_impl<type_list<T0, T...>, false, S...> {
template <class T0, class... T, bool... S> template <class T0, class... T, bool... S>
struct tl_filter_impl<type_list<T0, T...>, true, S...> { struct tl_filter_impl<type_list<T0, T...>, true, S...> {
using type = using type =
typename tl_prepend< tl_prepend_t<
typename tl_filter_impl< typename tl_filter_impl<
type_list<T...>, type_list<T...>,
S... S...
>::type, >::type,
T0 T0
>::type; >;
}; };
template <class List, template <class> class Pred> template <class List, template <class> class Pred>
...@@ -738,6 +823,9 @@ struct tl_filter<type_list<T...>, Pred> { ...@@ -738,6 +823,9 @@ struct tl_filter<type_list<T...>, Pred> {
>::type; >::type;
}; };
template <class List, template <class> class Pred>
using tl_filter_t = typename tl_filter<List, Pred>::type;
/// Creates a new list containing all elements which /// Creates a new list containing all elements which
/// do not satisfy `Pred`. /// do not satisfy `Pred`.
template <class List, template <class> class Pred> template <class List, template <class> class Pred>
...@@ -757,6 +845,9 @@ struct tl_filter_not<type_list<T...>, Pred> { ...@@ -757,6 +845,9 @@ struct tl_filter_not<type_list<T...>, Pred> {
>::type; >::type;
}; };
template <class List, template <class> class Pred>
using tl_filter_not_t = typename tl_filter_not<List, Pred>::type;
/// Creates a new list containing all elements which /// Creates a new list containing all elements which
/// are equal to `Type`. /// are equal to `Type`.
template <class List, class Type> template <class List, class Type>
...@@ -788,6 +879,9 @@ struct tl_filter_not_type<type_list<T...>, Type> { ...@@ -788,6 +879,9 @@ struct tl_filter_not_type<type_list<T...>, Type> {
>::type; >::type;
}; };
template <class List, class T>
using tl_filter_not_type_t = typename tl_filter_not_type<List, T>::type;
// list distinct(list) // list distinct(list)
/// Creates a new list from `List` without any duplicate elements. /// Creates a new list from `List` without any duplicate elements.
...@@ -802,26 +896,33 @@ struct tl_distinct<empty_type_list> { ...@@ -802,26 +896,33 @@ struct tl_distinct<empty_type_list> {
template <class T0, class... Ts> template <class T0, class... Ts>
struct tl_distinct<type_list<T0, Ts...>> { struct tl_distinct<type_list<T0, Ts...>> {
using type = using type =
typename tl_concat< tl_concat_t<
type_list<T0>, type_list<T0>,
typename tl_distinct< typename tl_distinct<
typename tl_filter_type< tl_filter_type_t<
type_list<Ts...>, type_list<Ts...>,
T0 T0
>
>::type >::type
>::type >;
>::type;
}; };
template <class List>
using tl_distinct_t = typename tl_distinct<List>::type;
// bool is_distinct // bool is_distinct
/// Tests whether a list is distinct. /// Tests whether a list is distinct.
template <class L> template <class List>
struct tl_is_distinct { struct tl_is_distinct {
static constexpr bool value = static constexpr bool value =
tl_size<L>::value == tl_size<typename tl_distinct<L>::type>::value; tl_size<List>::value == tl_size<tl_distinct_t<List>>::value;
}; };
// Uncomment after having switched to C++14
//template <class List>
//inline constexpr bool tl_is_distinct_v = tl_is_distinct<List>::value;
// list resize(list, size, fill_type) // list resize(list, size, fill_type)
template <class List, bool OldSizeLessNewSize, size_t OldSize, size_t NewSize, template <class List, bool OldSizeLessNewSize, size_t OldSize, size_t NewSize,
...@@ -830,7 +931,7 @@ struct tl_pad_right_impl; ...@@ -830,7 +931,7 @@ struct tl_pad_right_impl;
template <class List, size_t OldSize, size_t NewSize, class FillType> template <class List, size_t OldSize, size_t NewSize, class FillType>
struct tl_pad_right_impl<List, false, OldSize, NewSize, FillType> { struct tl_pad_right_impl<List, false, OldSize, NewSize, FillType> {
using type = typename tl_slice<List, 0, NewSize>::type; using type = tl_slice_t<List, 0, NewSize>;
}; };
template <class List, size_t Size, class FillType> template <class List, size_t Size, class FillType>
...@@ -842,7 +943,7 @@ template <class List, size_t OldSize, size_t NewSize, class FillType> ...@@ -842,7 +943,7 @@ template <class List, size_t OldSize, size_t NewSize, class FillType>
struct tl_pad_right_impl<List, true, OldSize, NewSize, FillType> { struct tl_pad_right_impl<List, true, OldSize, NewSize, FillType> {
using type = using type =
typename tl_pad_right_impl< typename tl_pad_right_impl<
typename tl_push_back<List, FillType>::type, tl_push_back_t<List, FillType>,
OldSize + 1 < NewSize, OldSize + 1 < NewSize,
OldSize + 1, OldSize + 1,
NewSize, NewSize,
...@@ -864,16 +965,16 @@ struct tl_pad_right { ...@@ -864,16 +965,16 @@ struct tl_pad_right {
>::type; >::type;
}; };
template <class List, size_t NewSize, class FillType = unit_t>
using tl_pad_right_t = typename tl_pad_right<List, NewSize, FillType>::type;
// bool pad_left(list, N) // bool pad_left(list, N)
template <class List, size_t OldSize, size_t NewSize, class FillType> template <class List, size_t OldSize, size_t NewSize, class FillType>
struct tl_pad_left_impl { struct tl_pad_left_impl {
using type = using type =
typename tl_pad_left_impl< typename tl_pad_left_impl<
typename tl_push_front< tl_push_front_t<List, FillType>,
List,
FillType
>::type,
OldSize + 1, OldSize + 1,
NewSize, NewSize,
FillType FillType
...@@ -899,6 +1000,9 @@ struct tl_pad_left { ...@@ -899,6 +1000,9 @@ struct tl_pad_left {
>::type; >::type;
}; };
template <class List, size_t NewSize, class FillType = unit_t>
using tl_pad_left_t = typename tl_pad_left<List, NewSize, FillType>::type;
// bool is_zipped(list) // bool is_zipped(list)
template <class List> template <class List>
...@@ -906,13 +1010,17 @@ struct tl_is_zipped { ...@@ -906,13 +1010,17 @@ struct tl_is_zipped {
static constexpr bool value = tl_forall<List, is_type_pair>::value; static constexpr bool value = tl_forall<List, is_type_pair>::value;
}; };
// Uncomment after having switched to C++14
//template <class List>
//inline constexpr bool tl_is_zipped_v = tl_is_zipped<List>::value;
/// Removes trailing `What` elements from the end. /// Removes trailing `What` elements from the end.
template <class List, class What = unit_t> template <class List, class What = unit_t>
struct tl_trim { struct tl_trim {
using type = using type =
typename std::conditional< typename std::conditional<
std::is_same<typename tl_back<List>::type, What>::value, std::is_same<typename tl_back<List>::type, What>::value,
typename tl_trim<typename tl_pop_back<List>::type,What>::type, typename tl_trim<tl_pop_back_t<List>, What>::type,
List List
>::type; >::type;
}; };
...@@ -922,18 +1030,23 @@ struct tl_trim<empty_type_list, What> { ...@@ -922,18 +1030,23 @@ struct tl_trim<empty_type_list, What> {
using type = empty_type_list; using type = empty_type_list;
}; };
template <class List, class What = unit_t>
using tl_trim_t = typename tl_trim<List, What>::type;
// list union(list1, list2) // list union(list1, list2)
template <class... Xs> template <class... Ts>
struct tl_union { struct tl_union {
using type = typename tl_distinct<typename tl_concat<Xs...>::type>::type; using type = tl_distinct_t<tl_concat_t<Ts...>>;
}; };
template <class... Ts>
using tl_union_t = typename tl_union<Ts...>::type;
// list intersect(list1, list2) // list intersect(list1, list2)
template <class List, template <class List,
bool HeadIsUnique = bool HeadIsUnique = tl_count_type<List, tl_head_t<List>>::value == 1>
tl_count_type<List, typename tl_head<List>::type>::value == 1>
struct tl_intersect_impl; struct tl_intersect_impl;
template <> template <>
...@@ -949,25 +1062,28 @@ struct tl_intersect_impl<type_list<T0, Ts...>, true> { ...@@ -949,25 +1062,28 @@ struct tl_intersect_impl<type_list<T0, Ts...>, true> {
template <class T0, class... Ts> template <class T0, class... Ts>
struct tl_intersect_impl<type_list<T0, Ts...>, false> { struct tl_intersect_impl<type_list<T0, Ts...>, false> {
using type = using type =
typename tl_concat< tl_concat_t<
type_list<T0>, type_list<T0>,
typename tl_intersect_impl< typename tl_intersect_impl<
typename tl_filter_type< tl_filter_type_t<
type_list<Ts...>, type_list<Ts...>,
T0 T0
>
>::type >::type
>::type >;
>::type;
}; };
template <class... Ts> template <class... Ts>
struct tl_intersect { struct tl_intersect {
using type = using type =
typename tl_intersect_impl< typename tl_intersect_impl<
typename tl_concat<Ts...>::type tl_concat_t<Ts...>
>::type; >::type;
}; };
template <class... Ts>
using tl_intersect_t = typename tl_intersect<Ts...>::type;
// list group_by(list, predicate) // list group_by(list, predicate)
template <bool Append, class What, class Where> template <bool Append, class What, class Where>
...@@ -985,21 +1101,21 @@ struct tl_group_by_impl_step<false, What, List> { ...@@ -985,21 +1101,21 @@ struct tl_group_by_impl_step<false, What, List> {
template <class In, class Out, template <class, typename> class Pred> template <class In, class Out, template <class, typename> class Pred>
struct tl_group_by_impl { struct tl_group_by_impl {
using last_group = typename tl_back<Out>::type; using last_group = tl_back_t<Out>;
using suffix = using suffix =
typename tl_group_by_impl_step< typename tl_group_by_impl_step<
Pred< Pred<
typename tl_head<In>::type, tl_head<In>,
typename tl_back<last_group>::type tl_back<last_group>
>::value, >::value,
typename tl_head<In>::type, tl_head_t<In>,
last_group last_group
>::type; >::type;
using prefix = typename tl_pop_back<Out>::type; using prefix = tl_pop_back_t<Out>;
using new_out = typename tl_concat<prefix, suffix>::type; using new_out = tl_concat_t<prefix, suffix>;
using type = using type =
typename tl_group_by_impl< typename tl_group_by_impl<
typename tl_tail<In>::type, tl_tail_t<In>,
new_out, new_out,
Pred Pred
>::type; >::type;
...@@ -1030,6 +1146,9 @@ struct tl_group_by { ...@@ -1030,6 +1146,9 @@ struct tl_group_by {
>::type; >::type;
}; };
template <class List, template <class, typename> class Pred>
using tl_group_by_t = typename tl_group_by<List, Pred>::type;
/// Applies the types of the list to `VarArgTemplate`. /// Applies the types of the list to `VarArgTemplate`.
template <class List, template <class...> class VarArgTemplate> template <class List, template <class...> class VarArgTemplate>
struct tl_apply; struct tl_apply;
...@@ -1039,6 +1158,9 @@ struct tl_apply<type_list<Ts...>, VarArgTemplate> { ...@@ -1039,6 +1158,9 @@ struct tl_apply<type_list<Ts...>, VarArgTemplate> {
using type = VarArgTemplate<Ts...>; using type = VarArgTemplate<Ts...>;
}; };
template <class List, template <class...> class VarArgTemplate>
using tl_apply_t = typename tl_apply<List, VarArgTemplate>::type;
// contains(list, x) // contains(list, x)
template <class List, class X> template <class List, class X>
...@@ -1053,6 +1175,10 @@ struct tl_contains<type_list<X, Ts...>, X> : std::true_type {}; ...@@ -1053,6 +1175,10 @@ struct tl_contains<type_list<X, Ts...>, X> : std::true_type {};
template <class T, class... Ts, class X> template <class T, class... Ts, class X>
struct tl_contains<type_list<T, Ts...>, X> : tl_contains<type_list<Ts...>, X> {}; struct tl_contains<type_list<T, Ts...>, X> : tl_contains<type_list<Ts...>, X> {};
// Uncomment after having switched to C++14
//template <class List, class X>
//inline constexpr bool tl_contains_v = tl_contains<List, X>::value;
// subset_of(list, list) // subset_of(list, list)
template <class ListA, class ListB, bool Fwd = true> template <class ListA, class ListB, bool Fwd = true>
...@@ -1068,6 +1194,10 @@ template <class T, class... Ts, class List> ...@@ -1068,6 +1194,10 @@ template <class T, class... Ts, class List>
struct tl_subset_of<type_list<T, Ts...>, List> struct tl_subset_of<type_list<T, Ts...>, List>
: tl_subset_of<type_list<Ts...>, List, tl_contains<List, T>::value> {}; : tl_subset_of<type_list<Ts...>, List, tl_contains<List, T>::value> {};
// Uncomment after having switched to C++14
// template <class ListA, class ListB, bool Fwd = true>
// inline constexpr bool tl_subset_of_v = tl_subset_of<ListA, ListB, Fwd>::value;
/// Tests whether ListA contains the same elements as ListB /// Tests whether ListA contains the same elements as ListB
/// and vice versa. This comparison ignores element positions. /// and vice versa. This comparison ignores element positions.
template <class ListA, class ListB> template <class ListA, class ListB>
...@@ -1076,9 +1206,13 @@ struct tl_equal { ...@@ -1076,9 +1206,13 @@ struct tl_equal {
&& tl_subset_of<ListB, ListA>::value; && tl_subset_of<ListB, ListA>::value;
}; };
// Uncomment after having switched to C++14
// template <class ListA, class ListB>
// inline constexpr bool tl_equal_v = tl_equal<ListA, ListB>::value;
template <size_t N, class T> template <size_t N, class T>
struct tl_replicate { struct tl_replicate {
using type = typename tl_cons<T, typename tl_replicate<N - 1, T>::type>::type; using type = tl_cons_t<T, typename tl_replicate<N - 1, T>::type>;
}; };
template <class T> template <class T>
...@@ -1086,6 +1220,9 @@ struct tl_replicate<0, T> { ...@@ -1086,6 +1220,9 @@ struct tl_replicate<0, T> {
using type = type_list<>; using type = type_list<>;
}; };
template <size_t N, class T>
using tl_replicate_t = typename tl_replicate<N, T>::type;
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment