#include <iostream>

template <typename...> struct InterlacePacksHelper;

template <template <typename...> class PRes, typename... Ts,
          template <typename...> class P, typename U, typename... Us,
          typename... Packs>
struct InterlacePacksHelper<PRes<Ts...>, P<U, Us...>, Packs...>
{
    using type = typename InterlacePacksHelper<PRes<Ts..., U>, Packs..., P<Us...>>::type;
};

template <template <typename...> class PRes, typename... Ts>
struct InterlacePacksHelper<PRes<Ts...>>
{
    using type = PRes<Ts...>;
};

template <template <typename...> class PRes, typename... Ts,
          template <typename...> class P,
          typename... Packs>
struct InterlacePacksHelper<PRes<Ts...>, P<>, Packs...>
{
    using type = typename InterlacePacksHelper<PRes<Ts...>, Packs...>::type;
};


// Finally, InterlacePacks itself.
template <typename...> struct InterlacePacks;

template <template <typename...> class P, typename... Ts, typename... Packs>
struct InterlacePacks<P<Ts...>, Packs...> : InterlacePacksHelper<P<>, P<Ts...>, Packs...>::type
{
    using type = typename InterlacePacksHelper<P<>, P<Ts...>, Packs...>::type;
};

// test ----------------------------------------------------------------
template <typename...> struct Pack {};
template <typename...> struct Group {};
template <typename...> struct Wrap {};
struct Object {};  struct Blob {};

int main() {
    using TestPack1 = Pack<int, double, Object>;  // 3 types
    using TestPack2 = Group<double, std::string, int, short, long>;  // 5 types
    using TestPack3 = Wrap<char, short, Blob, std::string>;  // 4 types
    InterlacePacks<TestPack1, TestPack2, TestPack3>::type interlacedPack;
    std::cout << std::boolalpha << std::is_same< decltype(interlacedPack),
        Pack<int, double, char, double, std::string, short, Object, int, Blob, short, std::string, long> >::value << std::endl;  // true
}
