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...>> {
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)
/// Gets the first element of `List`.
......@@ -89,6 +93,9 @@ struct tl_tail<type_list<T0, Ts...>> {
using type = type_list<Ts...>;
};
template <class List>
using tl_tail_t = typename tl_tail<List>::type;
// size_t size(type_list)
/// Gets the number of template parameters of `List`.
......@@ -103,6 +110,10 @@ struct tl_size<type_list<Ts...>> {
template <class... Ts>
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)
/// Gets the last element in `List`.
......@@ -126,6 +137,9 @@ struct tl_back<type_list<T0, T1, Ts...>> {
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)
/// Tests whether a list is empty.
......@@ -134,6 +148,10 @@ struct tl_empty {
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)
template <size_t LeftOffset,
......@@ -147,7 +165,7 @@ struct tl_slice_impl {
LeftOffset - 1,
Remaining,
PadType,
typename tl_tail<List>::type,
tl_tail_t<List>,
Ts...
>::type;
};
......@@ -159,9 +177,9 @@ struct tl_slice_impl<0, Remaining, PadType, List, Ts...> {
0,
Remaining - 1,
PadType,
typename tl_tail<List>::type,
tl_tail_t<List>,
Ts...,
typename tl_head<List>::type
tl_head_t<List>
>::type;
};
......@@ -217,11 +235,14 @@ struct tl_slice {
>::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.
template <class List, size_t NewSize, size_t OldSize = tl_size<List>::value>
struct tl_right {
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>
......@@ -239,6 +260,9 @@ struct tl_right<empty_type_list, 0, 0> {
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, typename> class Fun = to_type_pair>
struct tl_zip_impl;
......@@ -263,23 +287,29 @@ struct tl_zip {
static constexpr size_t result_size = (sizea < sizeb) ? sizea : sizeb;
using type =
typename tl_zip_impl<
typename tl_slice<ListA, 0, result_size>::type,
typename tl_slice<ListB, 0, result_size>::type,
tl_slice_t<ListA, 0, result_size>,
tl_slice_t<ListB, 0, result_size>,
Fun
>::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)`.
template <class ListA, class ListB, template <class, class> class Fun, size_t N>
struct tl_zip_right {
using type =
typename tl_zip_impl<
typename tl_right<ListA, N>::type,
typename tl_right<ListB, N>::type,
tl_right_t<ListA, N>,
tl_right_t<ListB, N>,
Fun
>::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,
typename PadA = unit_t, typename PadB = unit_t,
template <class, typename> class Fun = to_type_pair>
......@@ -295,6 +325,11 @@ struct tl_zip_all {
>::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>
struct tl_unzip;
......@@ -334,6 +369,10 @@ struct tl_index_of<type_list<Ts...>, T> {
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)
template <int Pos, template <class> class Pred, class... Ts>
......@@ -359,6 +398,10 @@ struct tl_index_where<type_list<Ts...>, Pred> {
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()
template <class From, class... Elements>
......@@ -380,6 +423,9 @@ struct tl_reverse {
using type = typename tl_reverse_impl<List>::type;
};
template <class List>
using tl_reverse_t = typename tl_reverse<List>::type;
// type find(list, predicate)
/// 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;
template <class List, template <class> class Pred>
struct tl_forall {
static constexpr bool value =
Pred<typename tl_head<List>::type>::value
&& tl_forall<typename tl_tail<List>::type, Pred>::value;
Pred<tl_head_t<List>>::value
&& tl_forall<tl_tail_t<List>, Pred>::value;
};
template <template <class> class Pred>
......@@ -428,13 +474,15 @@ struct tl_forall<empty_type_list, Pred> {
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>
struct tl_forall2_impl {
static constexpr bool value =
Pred<typename tl_head<ListA>::type,
typename tl_head<ListB>::type>::value
&& tl_forall2_impl<typename tl_tail<ListA>::type,
typename tl_tail<ListB>::type, Pred>::value;
Pred<tl_head_t<ListA>, tl_head_t<ListB>>::value
&& tl_forall2_impl<tl_tail_t<ListA>, tl_tail_t<ListB>, Pred>::value;
};
template <template <class, typename> class Pred>
......@@ -451,19 +499,21 @@ struct tl_binary_forall {
&& 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.
template <class List, template <class> class Pred>
struct tl_exists {
static constexpr bool value =
Pred<typename tl_head<List>::type>::value
|| tl_exists<typename tl_tail<List>::type, Pred>::value;
Pred<tl_head_t<List>>::value || tl_exists<tl_tail_t<List>, Pred>::value;
};
template <template <class> class Pred>
struct tl_exists<empty_type_list, Pred> {
static constexpr bool value = false;
};
// Uncomment after having switched to C++14
//template <class List, template <class> class Pred>
//inline constexpr bool tl_exists_v = tl_exists<List, Pred>::value;
// size_t count(predicate)
......@@ -471,8 +521,8 @@ struct tl_exists<empty_type_list, Pred> {
template <class List, template <class> class Pred>
struct tl_count {
static constexpr size_t value =
(Pred<typename tl_head<List>::type>::value ? 1 : 0)
+ tl_count<typename tl_tail<List>::type, Pred>::value;
(Pred<tl_head_t<List>>::value ? 1 : 0)
+ tl_count<tl_tail_t<List>, Pred>::value;
};
template <template <class> class Pred>
......@@ -483,14 +533,18 @@ struct tl_count<empty_type_list, Pred> {
template <class List, template <class> class Pred>
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)
/// Counts the number of elements in the list which are equal to `T`.
template <class List, class T>
struct tl_count_type {
static constexpr size_t value =
(std::is_same<typename tl_head<List>::type, T>::value ? 1 : 0)
+ tl_count_type<typename tl_tail<List>::type, T>::value;
(std::is_same<tl_head_t<List>, T>::value ? 1 : 0)
+ tl_count_type<tl_tail_t<List>, T>::value;
};
template <class T>
......@@ -501,23 +555,30 @@ struct tl_count_type<empty_type_list, T> {
template <class List, class T>
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)
/// Counts the number of elements in the list which satisfy a predicate.
template <class List, template <class> class Pred>
struct tl_count_not {
static constexpr size_t value =
(Pred<typename tl_head<List>::type>::value ? 0 : 1) +
tl_count_not<typename tl_tail<List>::type, Pred>::value;
(Pred<tl_head_t<List>>::value ? 0 : 1) +
tl_count_not<tl_tail_t<List>, Pred>::value;
};
template <template <class> class Pred>
struct tl_count_not<empty_type_list, Pred> {
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>
struct tl_concat_impl;
......@@ -547,6 +608,9 @@ struct tl_concat<List0, List1, Lists...> {
>::type;
};
template <class... Lists>
using tl_concat_t = typename tl_concat<Lists...>::type;
// list push_back(list, type)
template <class List, class What>
......@@ -556,9 +620,11 @@ struct tl_push_back;
template <class... ListTs, class What>
struct tl_push_back<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>
struct tl_push_front;
......@@ -568,12 +634,18 @@ struct tl_push_front<type_list<ListTs...>, What> {
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>`.
template <class What, class List>
struct tl_cons : tl_push_front<List, What> {
// nop
};
template <class List, class What>
using tl_cons_t = tl_push_front_t<List, What>;
// list map(list, trait)
template <class T, template <class> class... Funs>
......@@ -589,13 +661,16 @@ struct tl_apply_all<T, Fun0, Funs...> {
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.
template <class List, template <class> class... Funs>
struct tl_map;
template <class... Ts, template <class> class... 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>
......@@ -607,19 +682,16 @@ template <class List, template <class> class Trait, bool TRes,
template <class> class... Funs>
struct tl_map_conditional {
using type =
typename tl_concat<
tl_concat_t<
type_list<
typename std::conditional<
Trait<typename tl_head<List>::type>::value == TRes,
typename tl_apply_all<typename tl_head<List>::type, Funs...>::type,
typename tl_head<List>::type
Trait<tl_head_t<List>>::value == TRes,
tl_apply_all_t<tl_head_t<List>, Funs...>,
tl_head_t<List>
>::type
>,
typename tl_map_conditional<
typename tl_tail<List>::type,
Trait, TRes, Funs...
>::type
>::type;
typename tl_map_conditional<tl_tail_t<List>, Trait, TRes, Funs...>::type
>;
};
template <template <class> class Trait, bool TraitResult,
......@@ -641,6 +713,9 @@ struct tl_pop_back<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()
/// 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...>> {
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)
template <size_t N, class... E>
......@@ -686,6 +765,9 @@ struct tl_at<type_list<E...>, N> {
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)
template <class List, class What>
......@@ -697,6 +779,9 @@ struct tl_prepend<type_list<T...>, What> {
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_not(predicate)
......@@ -716,13 +801,13 @@ struct tl_filter_impl<type_list<T0, T...>, false, S...> {
template <class T0, class... T, bool... S>
struct tl_filter_impl<type_list<T0, T...>, true, S...> {
using type =
typename tl_prepend<
tl_prepend_t<
typename tl_filter_impl<
type_list<T...>,
S...
>::type,
T0
>::type;
>;
};
template <class List, template <class> class Pred>
......@@ -738,6 +823,9 @@ struct tl_filter<type_list<T...>, Pred> {
>::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
/// do not satisfy `Pred`.
template <class List, template <class> class Pred>
......@@ -757,6 +845,9 @@ struct tl_filter_not<type_list<T...>, Pred> {
>::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
/// are equal to `Type`.
template <class List, class Type>
......@@ -788,6 +879,9 @@ struct tl_filter_not_type<type_list<T...>, Type> {
>::type;
};
template <class List, class T>
using tl_filter_not_type_t = typename tl_filter_not_type<List, T>::type;
// list distinct(list)
/// Creates a new list from `List` without any duplicate elements.
......@@ -802,26 +896,33 @@ struct tl_distinct<empty_type_list> {
template <class T0, class... Ts>
struct tl_distinct<type_list<T0, Ts...>> {
using type =
typename tl_concat<
tl_concat_t<
type_list<T0>,
typename tl_distinct<
typename tl_filter_type<
tl_filter_type_t<
type_list<Ts...>,
T0
>
>::type
>::type
>::type;
>;
};
template <class List>
using tl_distinct_t = typename tl_distinct<List>::type;
// bool is_distinct
/// Tests whether a list is distinct.
template <class L>
template <class List>
struct tl_is_distinct {
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)
template <class List, bool OldSizeLessNewSize, size_t OldSize, size_t NewSize,
......@@ -830,7 +931,7 @@ struct tl_pad_right_impl;
template <class List, size_t OldSize, size_t NewSize, class 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>
......@@ -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> {
using type =
typename tl_pad_right_impl<
typename tl_push_back<List, FillType>::type,
tl_push_back_t<List, FillType>,
OldSize + 1 < NewSize,
OldSize + 1,
NewSize,
......@@ -864,16 +965,16 @@ struct tl_pad_right {
>::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)
template <class List, size_t OldSize, size_t NewSize, class FillType>
struct tl_pad_left_impl {
using type =
typename tl_pad_left_impl<
typename tl_push_front<
List,
FillType
>::type,
tl_push_front_t<List, FillType>,
OldSize + 1,
NewSize,
FillType
......@@ -899,6 +1000,9 @@ struct tl_pad_left {
>::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)
template <class List>
......@@ -906,13 +1010,17 @@ struct tl_is_zipped {
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.
template <class List, class What = unit_t>
struct tl_trim {
using type =
typename std::conditional<
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
>::type;
};
......@@ -922,18 +1030,23 @@ struct tl_trim<empty_type_list, What> {
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)
template <class... Xs>
template <class... Ts>
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)
template <class List,
bool HeadIsUnique =
tl_count_type<List, typename tl_head<List>::type>::value == 1>
bool HeadIsUnique = tl_count_type<List, tl_head_t<List>>::value == 1>
struct tl_intersect_impl;
template <>
......@@ -949,25 +1062,28 @@ struct tl_intersect_impl<type_list<T0, Ts...>, true> {
template <class T0, class... Ts>
struct tl_intersect_impl<type_list<T0, Ts...>, false> {
using type =
typename tl_concat<
tl_concat_t<
type_list<T0>,
typename tl_intersect_impl<
typename tl_filter_type<
tl_filter_type_t<
type_list<Ts...>,
T0
>
>::type
>::type
>::type;
>;
};
template <class... Ts>
struct tl_intersect {
using type =
typename tl_intersect_impl<
typename tl_concat<Ts...>::type
tl_concat_t<Ts...>
>::type;
};
template <class... Ts>
using tl_intersect_t = typename tl_intersect<Ts...>::type;
// list group_by(list, predicate)
template <bool Append, class What, class Where>
......@@ -985,21 +1101,21 @@ struct tl_group_by_impl_step<false, What, List> {
template <class In, class Out, template <class, typename> class Pred>
struct tl_group_by_impl {
using last_group = typename tl_back<Out>::type;
using last_group = tl_back_t<Out>;
using suffix =
typename tl_group_by_impl_step<
Pred<
typename tl_head<In>::type,
typename tl_back<last_group>::type
tl_head<In>,
tl_back<last_group>
>::value,
typename tl_head<In>::type,
tl_head_t<In>,
last_group
>::type;
using prefix = typename tl_pop_back<Out>::type;
using new_out = typename tl_concat<prefix, suffix>::type;
using prefix = tl_pop_back_t<Out>;
using new_out = tl_concat_t<prefix, suffix>;
using type =
typename tl_group_by_impl<
typename tl_tail<In>::type,
tl_tail_t<In>,
new_out,
Pred
>::type;
......@@ -1030,6 +1146,9 @@ struct tl_group_by {
>::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`.
template <class List, template <class...> class VarArgTemplate>
struct tl_apply;
......@@ -1039,6 +1158,9 @@ struct tl_apply<type_list<Ts...>, VarArgTemplate> {
using type = VarArgTemplate<Ts...>;
};
template <class List, template <class...> class VarArgTemplate>
using tl_apply_t = typename tl_apply<List, VarArgTemplate>::type;
// contains(list, x)
template <class List, class X>
......@@ -1053,6 +1175,10 @@ struct tl_contains<type_list<X, Ts...>, X> : std::true_type {};
template <class T, class... Ts, class 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)
template <class ListA, class ListB, bool Fwd = true>
......@@ -1068,6 +1194,10 @@ template <class T, class... Ts, class List>
struct tl_subset_of<type_list<T, Ts...>, List>
: 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
/// and vice versa. This comparison ignores element positions.
template <class ListA, class ListB>
......@@ -1076,9 +1206,13 @@ struct tl_equal {
&& 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>
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>
......@@ -1086,6 +1220,9 @@ struct tl_replicate<0, T> {
using type = type_list<>;
};
template <size_t N, class T>
using tl_replicate_t = typename tl_replicate<N, T>::type;
} // namespace detail
} // 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