I would like to split a template parameter pack. Something like this. How could I go about doing this?
template< typename... Pack >
struct TypeB : public TypeA< get<0, sizeof...(Pack)/2>(Pack...) >
, public TypeA< get<sizeof...(Pack)/2, sizeof...(Pack)>(Pack...) >
{
};
Here is my take on why this question is not a duplicate: I am looking for a generalised way to do this that will work when passing the split pack to other template classes - as shown above. As well as passing it to functions.
With std::tuple
(C++11) and std::index_sequence
(C++14, but there are backports), the standard library contains everything to efficiently and somewhat conveniently split the pack.
template <class, class, class>
struct TypeBImpl;
template <std::size_t... N, std::size_t... M, class T>
struct TypeBImpl<std::index_sequence<N...>, std::index_sequence<M...>, T>
: TypeA<typename std::tuple_element_t<T, N>::type...>
, TypeA<typename std::tuple_element_t<T, M + sizeof...(N)>::type...>
{};
template <class... Ts>
struct TypeB
: TypeBImpl<
std::make_index_sequence<sizeof...(Ts) / 2>,
std::make_index_sequence<(sizeof...(Ts) + 1) / 2>,
std::tuple<std::enable_if<1, Ts>...>
>
{};
I used an intermediate base for convenience, which has the added advantage of keeping the helper-types for re-use in members.
If you don't need it, or its existence in RTTI is inconvenient, there are other solutions:
template <class T, std::size_t N, std::size_t... M>
auto TypeA_part_impl(std::index_sequence<M...>)
-> TypeA<typename std::tuple_element_t<T, N + M>::type...>;
template <bool tail, class... Ts>
using TypeA_part = decltype(TypeA_part_impl<
std::tuple<std::enable_if<1, Ts>...>,
tail * sizeof...(Ts) / 2>(
std::make_index_sequence<(sizeof...(Ts) + tail) / 2>()));
template <class... Ts>
struct TypeB : TypeA_part<0, Ts...>, TypeA_part<1, Ts...>
{
};
I'm using std::enable_if<1, T>
as a convenient vehicle to transfer arbitrary type-information, even if the type is so irregular it cannot be stored in a std::tuple
, or is incomplete. No need to define my own.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With