Is it possible, with C++11/14/1z, to have a templated construct with two parameter packs, and within it, instantiate some other templated construct with the two packs inteleaved? i.e. if the first pack is T1_1, T1_2, T1_3 and the second pack is T2_1, T2_2 and T2_3, the interleaved pack will be T1_1, T2_1, T1_2, T2_2, T1_3, T2_3? My guess would be "no", since an ellipsis should not be able to apply to two parameter pack element designators; but perhaps some kind of tuple-construction or recursive-instantiation trick could work?
Edit: Let me be explicit in assuming the packs have equal lengths (sizeof...
values). A solution for packs of different lengths would be nice provided it doesn't make things much more convoluted.
[edit] A template parameter pack is a template parameter that accepts zero or more template arguments (non-types, types, or templates). A function parameter pack is a function parameter that accepts zero or more function arguments. A template with at least one parameter pack is called a variadic template.
All the individual pieces for this have actually already been added to the standard. I can't test this myself right now but the idea should work.
template <class Tuple1, class Tuple2, std::size_t ... indices>
auto interleave(Tuple1 t1, Tuple2 t2, std::integer_sequence<std::size_t, indices...>)
{
return std::tuple_cat(std::make_tuple(std::get<indices>(t1),
std::get<indices>(t2))...);
}
template <class Tuple1, class Tuple2>
auto interleave(Tuple1 t1, Tuple2 t2)
{
return interleave(t1, t2, std::make_index_sequence<std::tuple_size<Tuple1>::value>());
}
Using tuple_cat
is overkill. Not to mention unnecessarily constraining.
Trivial pack class:
template<class...> struct pack {};
A variadic concat, fairly trivial to write:
template<class T = pack<>, class...>
struct concat { using type = T; };
template<class... T1, class... T2, class... Ts>
struct concat<pack<T1...>, pack<T2...>, Ts...>
: concat<pack<T1..., T2...>, Ts...> {};
template<class... Ts>
using concat_t = typename concat<Ts...>::type;
Then interleave itself is equally trivial - expand into pack of two types, then concatenate them:
template<class... Us>
struct interleave {
template<class... Vs>
using with = concat_t<pack<Us, Vs>...>;
};
Demo.
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