A class template that just holds a parameter pack.The idea came from MPL's sequence concept [link1 1] and from N4115 [link2 2]. In addition to N4115's name "packer" we just prefer a name which is object, not a subject. This way the name gives the feeling of a container and smells like Python.
In addition to tuple we lack members, so typelist could serve as an empty base class, and an object of the ultimate type could always be instantiated (even if the parameter typelist contains void or some type that lacks a default constructor).
#ifndef __utl_meta_typelist_h__
#define __utl_meta_typelist_h__
namespace meta {
template <typename... Ts>
struct typelist {
static constexpr
size_t size() noexcept {
return sizeof...(Ts);
}
static constexpr
bool empty() noexcept {
return (sizeof...(Ts) == 0);
}
private:
template <typename... > struct cat_ { };
template <typename... L1, typename... L2>
struct cat_<typelist<L1...>, typelist<L2...>> {
using type = typelist<L1..., L2...>;
};
template <size_t N, typename ...T>
struct times_ {
cat_<
eval<times_<N - N/2, T...>>
>
>;
};
template <typename ...T>
struct times_<1, T...> {
using type = typelist<T...>;
};
template <typename ...T>
struct times_<0, T...> {
};
public:
template<size_t N>
times_<N, Ts...>
>;
};
template <typename List>
using size = size_<List::size()>;
template <typename List>
using empty = bool_<List::empty()>;
template <typename T1, typename T2>
using pair = typelist<T1, T2>;
template <size_t N, typename ...Ts>
using repeat_c =
typename typelist<Ts...>::template times<N>;
template <typename N, typename ...Ts>
namespace apply_impl {
template <typename Fn, typename Seq>
struct apply_ { };
template<typename Fn, typename ...List>
struct apply_<Fn, typelist<List...>> {
using type =
invoke<Fn, List...>;
};
template <typename Fn, typename T, T... Is>
using type = invoke<Fn, integral_<T, Is>...>;
};
}
template <typename Fn, typename Seq>
using apply = apply_impl::apply_<Fn, Seq>;
template <typename Fn, typename Seq>
using apply_t = eval <apply<Fn, Seq>>;
namespace at_impl {
template <
typename T>
struct _add_pointer {
using type = T*; };
template <
typename T>
using add_pointer = eval < _add_pointer <T> >;
template <typename ...>
struct at_head_ { };
template <typename... voids>
struct at_head_ <typelist<voids...>> {
template <typename T> static constexpr T select(voids..., T*, ...);
static constexpr nil_ select (...);
};
template<typename List, index_t N>
struct at_ { };
template<
typename... List,
index_t N>
struct at_<typelist<List...>, N> {
using head_ = at_head_<typelist<void*>::times<N>>;
using type = decltype(
head_::select(static_cast<add_pointer<List>>(nullptr)...)
);
};
}
template <typename List, index_t N>
at_impl::at_<List, N>
>;
template <typename List, typename N>
using at = at_c<List, N::type::value>;
namespace front_impl {
template <typename L>
struct front_ { };
template <typename Head, typename... Tail>
struct front_<typelist<Head, Tail...>> {
using type = Head;
};
}
template <typename List>
front_impl::front_<List>
>;
namespace back_impl {
template <typename List>
struct back_ { };
template <typename Head, typename... Tail>
struct back_<typelist<Head, Tail...>> {
typelist<Head, Tail...>, sizeof...(Tail)
>;
};
}
template <typename List>
back_impl::back_<List>
>;
namespace cat_impl {
template <typename... Lists>
struct cat_ { };
template <>
struct cat_<> {
using type = typelist<>;
};
template <typename... L1>
struct cat_<typelist<L1...>> {
using type = typelist<L1...>;
};
template <typename... L1, typename... L2>
struct cat_<typelist<L1...>, typelist<L2...>> {
using type = typelist<L1..., L2...>;
};
template <typename... L1, typename... L2, typename... Ln>
struct cat_<typelist<L1...>, typelist<L2...>, Ln...>
: cat_ <typelist<L1..., L2...>, Ln...> { };
}
template <typename... Lists>
cat_impl::cat_<Lists...>
>;
namespace fold_impl {
template<typename, typename, typename>
struct fold_ { };
template<typename Head, typename... Tail,
typename V,
typename Fn>
struct fold_<typelist<Head, Tail...>, V, Fn> {
fold_<
typelist<Tail...>,
invoke<Fn, V, Head>,
Fn
>
>;
};
template<typename V0, typename Fn>
struct fold_<typelist<>, V0, Fn> {
using type = V0;
};
}
template <typename List, typename V, typename Fn>
using fold = eval<fold_impl::fold_<List, V, Fn>>;
template <typename List, typename V, typename Fn>
namespace rev_fold_impl {
template<typename, typename, typename>
struct rev_fold_ { };
template<typename Head, typename... Tail,
typename V,
typename Fn>
struct rev_fold_<typelist<Head, Tail...>, V, Fn> {
rev_fold_ <
typelist<Tail...>,
V,
Fn
>>
>;
};
template<typename Tail, typename V, typename Fn>
struct rev_fold_ <typelist<Tail>, V, Fn> {
using type = invoke<Fn, Tail, V>;
};
template<typename V, typename Fn>
struct rev_fold_ <typelist<>, V, Fn> {
using type = V;
};
}
template <typename List, typename V, typename Fn>
rev_fold_impl::rev_fold_<List, V, Fn>
>;
template <typename List, typename... Ts>
bind_front<quote<typelist>, Ts...>, List
>
>;
template <typename List, typename... Ts>
bind_back<quote<typelist>, Ts...>, List
>
>;
namespace reverse_impl {
template <typename List, typename V = typelist<>>
struct reverse_ {
using type = fold<List, V, quote<push_front>>;
};
}
template <typename List>
reverse_impl::reverse_<List>
>;
namespace pop_front_impl {
template <typename List>
struct pop_front_ { };
template <typename Head, typename... Tail>
struct pop_front_<typelist <Head, Tail...>> {
using type = typelist<Tail...>;
};
}
template <typename List>
pop_front_impl::pop_front_<List>
>;
namespace pop_back_impl {
template <typename List>
struct pop_back_ {
pop_front<reverse<List>>
>;
};
}
template <typename List>
pop_back_impl::pop_back_<List>
>;
namespace transform_impl {
template <typename, typename = void>
struct transform_ { };
template <typename... Ts, typename Fn>
struct transform_<typelist<typelist<Ts...>, Fn>,
using type = typelist<
invoke_t<Fn, Ts>...
>;
};
template <typename... Ts0, typename... Ts1, typename Fn>
struct transform_<typelist<typelist<Ts0...>, typelist<Ts1...>, Fn>,
using type = typelist<
invoke_t<Fn, Ts0, Ts1>...
>;
};
}
template <typename... Args>
transform_impl::transform_<typelist<Args...>>
>;
namespace transform_lazy_impl {
template <typename, typename = void>
struct transform_lazy_ { };
template <typename... Ts, typename Fn>
struct transform_lazy_<typelist<typelist<Ts...>, Fn>,
using type = typelist<
invoke<Fn, Ts>...
>;
};
template <typename... Ts0, typename... Ts1, typename Fn>
struct transform_lazy_<typelist<typelist<Ts0...>, typelist<Ts1...>, Fn>,
using type = typelist<
invoke<Fn, Ts0, Ts1>...
>;
};
}
template <typename... Args>
transform_lazy_impl::transform_lazy_<typelist<Args...>>
>;
namespace find_if_impl {
template <typename, typename, index_t>
struct find_if_ { };
template<
typename Head,
typename... Tail,
typename Fn,
index_t N>
struct find_if_<typelist<Head, Tail...>, Fn, N> {
invoke_t<Fn, Head>,
index_<N>,
typelist<Tail...>, Fn, N+1>
>
>;
};
template<typename Fn, index_t N>
struct find_if_<typelist<>, Fn, N> {
};
}
template<typename List, typename Pred>
find_if_impl::find_if_<List, Pred, 0>
>;
template <typename List, typename T>
using find = find_if<List, same_as<T>>;
namespace seek_if_impl {
template <typename, typename, index_t>
struct seek_if_ { };
template<
typename Head,
typename... Tail,
typename Fn,
index_t N>
struct seek_if_<typelist<Head, Tail...>, Fn, N> {
invoke_t<Fn, Head>,
typelist<Head, Tail...>,
typelist<Tail...>, Fn, N+1>
>
>;
};
template<typename Fn, index_t N>
struct seek_if_<typelist<>, Fn, N> {
using type = typelist<>;
};
}
template <typename List, typename Pred>
seek_if_impl::seek_if_<List, Pred, 0>
>;
template <typename List, typename T>
using seek = seek_if <List, same_as<T>>;
namespace count_if_impl {
template <typename, typename, size_t>
struct count_if_ { };
template<typename Head, typename... Tail, typename Fn, size_t N>
struct count_if_<typelist<Head, Tail...>, Fn, N> {
invoke_t<Fn, Head>,
count_if_<typelist<Tail...>, Fn, N+1>
>,
count_if_<typelist<Tail...>, Fn, N>
>
>;
};
template<typename Fn, size_t N>
struct count_if_<typelist<>, Fn, N> {
using type = size_<N>;
};
}
template <typename List, typename Pred>
count_if_impl::count_if_<List, Pred, 0>
>;
template <typename List, typename T>
using count = count_if<List, same_as<T>>;
namespace filter_impl {
template <typename, typename, typename>
struct filter_ { };
template<typename Head, typename... Tail, typename Fn, typename L>
struct filter_<typelist<Head, Tail...>, Fn, L> {
invoke_t <Fn, Head>,
eval<filter_<typelist<Tail...>, Fn, cat<L, typelist<Head>>>>,
eval<filter_<typelist<Tail...>, Fn, L>>
>;
};
template<typename Fn, typename L>
struct filter_<typelist<>, Fn, L> {
using type = L;
};
}
template <typename List, typename Pred>
filter_impl::filter_<List, Pred, typelist<>>
>;
namespace replace_if_impl {
template <typename, typename, typename, typename>
struct replace_if_ { };
template <typename Head, typename... Tail, typename Fn, typename T, typename Ret>
struct replace_if_<typelist<Head, Tail...>, Fn, T, Ret> {
invoke_t<Fn, Head>,
eval<replace_if_<typelist<Tail...>, Fn, T, cat<Ret, typelist<T>>>>,
eval<replace_if_<typelist<Tail...>, Fn, T, cat<Ret, typelist<Head>>>>
>;
};
template <typename Fn, typename T, typename Ret>
struct replace_if_ <typelist<>, Fn, T, Ret> {
using type = Ret;
};
}
template<typename List, typename Pred, typename T>
replace_if_impl::replace_if_<List, Pred, T, typelist<>>
>;
template <typename List, typename T, typename U>
replace_if <List, same_as<T>, U>
>;
template <typename List, typename Pred>
empty <List>,
filter <List, compose<quote<not_>, Pred>>
>
>;
template <typename List, typename Pred>
empty<filter <List, Pred>>
>;
template <typename List, typename Pred>
filter <List, Pred>
>;
}}
#endif