c – 获得一包包
这是一个非常艰难的(至少对我而言).我将首先讨论一个我已经解决过的更简单的任务. ExpandPacks< Packs ...> :: type是从Packs中的每个包中获取一种类型获得的所有包的包….例如
ExpandPacks<P<int,char>,P<bool,double,long>>::type 是 P< P<int,bool>,P<int,double>,long>,P<char,long> > 我已经为任意数量的包编写了代码来执行此操作: #include <iostream> #include <type_traits> template <typename T,typename Pack> struct Prepend; template <typename...> struct Merge; template <typename T,template <typename...> class P,typename... Ts> struct Prepend<T,P<Ts...>> { using type = P<T,Ts...>; }; template <typename Pack> struct Merge<Pack> { using type = Pack; }; template <template <typename...> class P,typename... Ts,typename... Us> struct Merge<P<Ts...>,P<Us...>> { using type = P<Ts...,Us...>; }; template <typename First,typename... Rest> struct Merge<First,Rest...> : Merge<First,typename Merge<Rest...>::type> {}; template <typename... Packs> struct ExpandPacks; template <typename T,typename Pack> struct ExpandPacksHelper; template <typename T,typename PackOfPacks> struct ExpandPacksHelper2; template <typename Pack,typename PackOfPacks> struct ExpandPacksHelper3; template <template <typename...> class P,typename T,typename... Ts> struct ExpandPacksHelper<T,P<Ts...>> { using type = P<P<T,Ts>...>; }; template <template <typename...> class P,typename... Packs> struct ExpandPacksHelper2<T,P<Packs...>> { using type = P<typename Prepend<T,Packs>::type...>; }; template <template <typename...> class P,typename... Packs> struct ExpandPacksHelper3<P<Ts...>,P<Packs...>> : Merge<typename ExpandPacksHelper2<Ts,P<Packs...>>::type...> {}; template <template <typename...> class P,typename Pack> struct ExpandPacks<P<Ts...>,Pack> : Merge<typename ExpandPacksHelper<Ts,Pack>::type...> {}; template <typename First,typename... Rest> struct ExpandPacks<First,Rest...> : ExpandPacksHelper3<First,typename ExpandPacks<Rest...>::type> {}; // Testing template <typename...> struct P; int main() { std::cout << std::boolalpha << std::is_same< typename ExpandPacks<P<int,long>>::type,P< P<int,long> > >::value << 'n'; // true std::cout << std::is_same< typename ExpandPacksHelper3<P<short,float>,long> >>::type,P< P<short,int,P<short,char,P<float,long> > >::value << 'n'; // true std::cout << std::is_same< typename ExpandPacks<P<short,long> > >::value << 'n'; // true std::cout << std::is_same< typename ExpandPacks<P<int,short,float,long> > >::value << 'n'; // true } 但现在我想概括一下.不必总是从每个包中选择一种类型,而是必须从每个包中选择N种类型,其中N是模板参数.如果N超过某个包的大小,那么只需从该包中取出所有类型.应保留每个包装的类型顺序.但我完全被困在这里.另外,我没有指定输出包的任何特定顺序,这使得测试更加困难.这是一个例子: ExpandPacks<2,short>,long>>::type 是,按包装顺序, P< P<int,bool,long> > 通过从P
ExpandPacks<std::index_sequence<2,1>,long>>::type 意思是从P< int,short>取2 P< bool,long>中的1和1,一旦第一个问题解决了(或者立即解决这个问题,这将解决这两个问题),这应该是一个简单的扩展.由于没有指定输出包的顺序,我想测试输出的最简单方法是检查 ExpandPacks<1,long>>::type 或者, ExpandPacks<std::index_sequence<1,long> > 因为那必须减少到我已经解决的版本.如果没有人能这么快解决这个问题,我愿意提供赏金.谢谢. 更新:出于测试目的,我刚刚编写了一个程序来检查两个类型的类型是否相等,直到类型的排列:http://ideone.com/zb7NA7 解决方法
以下适用于两包(可轻松扩展):
#include <type_traits> template <typename...> struct pack {using type=pack;}; template <typename,typename> struct cat; template <typename... l,typename... r> struct cat<pack<l...>,pack<r...>> : pack<l...,r...> {}; template <typename T> using eval = typename T::type; //! N choose K namespace detail{ template <typename,typename,std::size_t,typename...> struct n_choose_k; template <typename head,typename... tail,std::size_t K,typename... prev> struct n_choose_k<std::enable_if_t<(sizeof...(tail)+1 >= K && K > 0)>,pack<head,tail...>,K,prev...> : cat<typename n_choose_k<void,pack<tail...>,K-1,prev...,head>::type,typename n_choose_k<void,prev...>::type> {}; template <typename... tail,typename... prev> struct n_choose_k<void,prev...> : pack<pack<prev...>> {}; template <typename... tail,typename... prev> struct n_choose_k<std::enable_if_t<(K > sizeof...(tail))>,prev...> : pack<> {}; } template <typename p,std::size_t k> using n_choose_k = eval<detail::n_choose_k<void,p,k>>; //! Interleave template <typename P,typename... Packs> using cat_all = pack<eval<cat<P,Packs>>...>; template <typename,typename> struct cross_interleave; template <typename l,typename... ls,typename... r> struct cross_interleave<pack<l,ls...>,pack<r...>> : eval<cat<typename cat_all<l,r...>::type,eval<cross_interleave<pack<ls...>,pack<r...>>>>> {}; template <typename... r> struct cross_interleave<pack<>,pack<r...>> : pack<> {}; template <typename A,std::size_t Na,typename B,std::size_t Nb> using interleave_multi = eval<cross_interleave<n_choose_k<A,Na>,n_choose_k<B,Nb>>>; 使用interleave_multi< pack< int,1,pack< bool,2>的示例用法: static_assert( std::is_same<interleave_multi<pack<int,pack<bool,2>,pack<pack<int,pack<int,long int>,pack<char,long int>>>{},"" ); Demo. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |