c – 变体模板:交错多个包

c – 变体模板:交错多个包,第1张

概述在开车回家时,我想到了这个问题:给了任何数量的包装,从每个包装中取出第一个类型,把它们放在一起.然后从每个包的第二个类型,把它们放在一起等等…然后合并他们.任何一个流浪者都会重复这个过程.例如,使用整数表示不同类型以获得更好的可读性, InterlacePacks<Pack<1 2 3 4>, Pack<5 6 7>, Pack<8 9 10 11 12>>::type 会给 Pack<1 5 8 在开车回家时,我想到了这个问题:给了任何数量的包装,从每个包装中取出第一个类型,把它们放在一起.然后从每个包的第二个类型,把它们放在一起等等…然后合并他们.任何一个流浪者都会重复这个过程.例如,使用整数表示不同类型以获得更好的可读性,
InterlacePacks<Pack<1 2 3 4>,Pack<5 6 7>,Pack<8 9 10 11 12>>::type

会给

Pack<1 5 8 2 6 9 3 7 10 4 11 12>

如果所有的包只有相同的尺寸,以下代码可以工作.当包装尺寸不同时,我现在完全处于“左侧”状态.这是我的代码到目前为止.我解释每个阶段,以便你知道我的计划是什么:

#include <iostream>// First a helper to remove the first N types from a pack:template <int,typename> struct Removehead;template <typename Pack>struct Removehead<0,Pack> { using type = Pack; };template <template <typename...> class P,typename First,typename... Rest>struct Removehead<0,P<First,Rest...>> { using type = P<First,Rest...>; };template <int N,template <typename...> class P,typename... Rest>struct Removehead<N,Rest...>> : Removehead<N-1,P<Rest...>> {};// Now a helper to merge multiple packs:template <typename...> struct MergePacks;template <typename Pack>struct MergePacks<Pack> {    using type = Pack;};// Final Pack type shall be the first one Listed,if there are different pack types.template <template <typename...> class P1,template <typename...> class P2,typename... Types1,typename... Types2,typename... Packs>struct MergePacks<P1<Types1...>,P2<Types2...>,Packs...> : MergePacks<P1<Types1...,Types2...>,Packs...> {};// First collect the first type from each pack:template <typename,typename...> struct InterlacePacksHelper1;template <template <typename...> class P,typename... Ts>struct InterlacePacksHelper1<P<Ts...>> { using type = P<Ts...>; };template <template <typename...> class P,template <typename...> class FirstPack,typename... Ts,typename... Rest,typename... Packs>struct InterlacePacksHelper1<P<Ts...>,FirstPack<First,Rest...>,Packs...> : InterlacePacksHelper1<P<Ts...,First>,Packs...> {};// Now remove the first type from each pack and repeat the process.  Use a parameter N as a counter,where N will start as the minimum size of the packs.template <int,typename,typename...> struct InterlacePacksHelper;template <template <typename...> class P,typename... Packs>struct InterlacePacksHelper<0,P<Ts...>,Packs...> { using type = P<Ts...>; };template <int N,typename... Packs>struct InterlacePacksHelper<N,Packs...> : InterlacePacksHelper<N-1,typename MergePacks<P<Ts...>,typename InterlacePacksHelper1<P<>,Packs...>::type>::type,typename Removehead<1,Packs>::type...> {};// Now obtain the smallest pack size,given a List of packs.template <int N,typename...> struct MinPackSize;template <int N>struct MinPackSize<N> : std::integral_constant<int,N> {};template <int N,typename... Types,typename... Packs>struct MinPackSize<N,P<Types...>,Packs...> : std::integral_constant<int,(sizeof...(Types) < N) ? sizeof...(Types) : N> {}; // Finally,InterlacePacks itself.template <typename...> struct InterlacePacks;template <template <typename...> class P,typename... Packs>struct InterlacePacks<P<Ts...>,Packs...> : InterlacePacksHelper<MinPackSize<sizeof...(Ts),Packs...>::value,P<>,Packs...> {};// 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,Blob,std::string>;  // 4 types    InterlacePacks<TestPack1,TestPack2,TestPack3>::type interlacedPack;    std::cout << std::boolAlpha << std::is_same< decltype(interlacedPack),Pack<int,char,Object,Blob> >::value << std::endl;  // true//  Want it to be Pack<int,long>}

那么如何修复代码,使所需的输出

Pack<int,long>

结果呢?

注意:我尝试使用MinPackSize的MaxPackSize intead,并且按预期不会编译.一个想法是在MinPackSize迭代后丢弃空包,并继续进行,直到MaxPackSize迭代完成(每次删除新的空包).这在理论上(还没有尝试过):

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,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...> {};
解决方法 这是我迄今为止最短的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,T<f>,P...> {};template <class... packs>using interlace = interlace_<std::tuple<>,packs...>;

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

总结

以上是内存溢出为你收集整理的c – 变体模板:交错多个包全部内容,希望文章能够帮你解决c – 变体模板:交错多个包所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1257851.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存