C++ 可变模板:交错多个包

C++ 可变模板:交错多个包,c++,templates,c++11,variadic,C++,Templates,C++11,Variadic,给定任意数量的包装,从每个包装中取出第一种类型,将它们放在一起。然后从每个包装中取出第二种,把它们放在一起,等等。。。然后将它们全部合并。任何左撇子都会在他们之间重复这个过程。例如,使用整数表示不同的类型以提高可读性 InterlacePacks<Pack<1 2 3 4>, Pack<5 6 7>, Pack<8 9 10 11 12>>::type 以下内容可能会有所帮助,它使用帮助器类并在第一个模板参数中聚合结果: template <

给定任意数量的包装,从每个包装中取出第一种类型,将它们放在一起。然后从每个包装中取出第二种,把它们放在一起,等等。。。然后将它们全部合并。任何左撇子都会在他们之间重复这个过程。例如,使用整数表示不同的类型以提高可读性

InterlacePacks<Pack<1 2 3 4>, Pack<5 6 7>, Pack<8 9 10 11 12>>::type

以下内容可能会有所帮助,它使用帮助器类并在第一个模板参数中聚合结果:

template <typename...> struct InterlacePacksHelper;

// general case: take first parameter and en-queue the Pack for further computation
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;
};

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

// Remove empty Pack.
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;
};
template struct InterlacePacksHelper;
//一般情况:获取第一个参数并将包排队以进行进一步计算
模板
结构层间打包机
{
使用type=typename InterlacePacksHelper::type;
};
//最终案例
模板
结构层间打包机
{
使用类型=压力;
};
//取出空包装。
模板
结构层间打包机
{
使用type=typename InterlacePacksHelper::type;
};
//最后,InterlacePacks本身。
模板结构层间包;
模板
结构InterlacePacks:InterlacePacksHelper::type
{
使用type=typename InterlacePacksHelper::type;
};

这是我迄今为止最短的C++11尝试:

template <class T, class...> struct interlace_ {using type = T;};
template <class... R,  template<class...> class T, class f, class... t, class... P>
struct interlace_<std::tuple<R...>, T<f, t...>, P...>
    : interlace_<std::tuple<R..., f>, P..., T<t...>> {};
template <class... R, template<class...> class T, class f, class... P>
struct interlace_<std::tuple<R...>, T<f>, P...>
    : interlace_<std::tuple<R..., f>, P...> {};

template <class... packs>
using interlace = interlace_<std::tuple<>, packs...>;
template struct interlace{using type=T;};
模板
结构交错_
:交错{};
模板
结构交错_
:交错{};
模板
使用隔行扫描=隔行扫描;

P
代表包,
R
是(当前)结果包,
f
是第一种类型,
t
是当前观察到的包的尾部
T
是保存包的模板。

好吧,如果你愿意,你可以发布一个c++14解决方案(总比没有解决方案好)。当然,我更关心的是如何进一步实现我自己的计划,即使用一些我以前从未听说过的库函数(不,我还没有学习过c++14)。因此,c++11解决方案是首选方案,但我欢迎您的c++14解决方案,因为我很快就会学习c++14。经过大量的过度复杂化,我终于找到了一个优雅的c++11解决方案。我没有修复你的代码,但Jarod42修复了。我希望有一个像你这样的简短而甜蜜的解决方案,避免将来像我这样的冗长的解决方案。不过,在您删除之前,我确实保存了较长的C++14解决方案(我假设它是C++14,因为它不会在我的C++11编译器上编译),并且无论如何都会研究它。你们太棒了,哇!你的解决方案如此简练,使我长久以来的尝试感到羞愧!我认为没有人能找到比这更短的解决方案!
Pack<int, double, char, double, std::string, short, Object, int, Blob, short, std::string, long>
template <typename, typename...> struct RemoveAllEmptyPacksHelper;

template <template <typename...> class P, typename... Packs> 
struct RemoveAllEmptyPacksHelper<P<Packs...>> : Identity<P<Packs...>> {};

template <template <typename...> class P, typename... CurrentPacks, template <typename...> class FirstPack, typename... Types, typename... Packs> 
struct RemoveAllEmptyPacksHelper<P<CurrentPacks...>, FirstPack<Types...>, Packs...> : 
    std::conditional<(sizeof...(Types) == 0),
    RemoveAllEmptyPacksHelper<P<CurrentPacks...>, Packs...>,
    RemoveAllEmptyPacksHelper<P<CurrentPacks..., FirstPack<Types...>>, Packs...>
    >::type {};

template <typename> struct RemoveAllEmptyPacks;

template <template <typename...> class P, typename... Packs> 
struct RemoveAllEmptyPacks<P<Packs...>> : RemoveAllEmptyPacksHelper<P<>, Packs...> {};
template <typename...> struct InterlacePacksHelper;

// general case: take first parameter and en-queue the Pack for further computation
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;
};

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

// Remove empty Pack.
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;
};
template <class T, class...> struct interlace_ {using type = T;};
template <class... R,  template<class...> class T, class f, class... t, class... P>
struct interlace_<std::tuple<R...>, T<f, t...>, P...>
    : interlace_<std::tuple<R..., f>, P..., T<t...>> {};
template <class... R, template<class...> class T, class f, class... P>
struct interlace_<std::tuple<R...>, T<f>, P...>
    : interlace_<std::tuple<R..., f>, P...> {};

template <class... packs>
using interlace = interlace_<std::tuple<>, packs...>;