Variadic templateへのあらゆる操作その2
前回書いていないようなメタ関数を書いてみたので一応。
※追記 改善を施しライブラリ化した
// First template<class...> struct First; template<class Head,class... Tail> struct First<Head,Tail...>{ typedef Head type; }; template<class Head,class... Tail> struct First<pack<Head,Tail...>>{ typedef Head type; }; template<class... Pack> using First_t=typename First<Pack...>::type; // Last template<class...> struct Last; template<class Head,class... Tail> struct Last<Head,Tail...>{ typedef typename Last<Tail...>::type type; }; template<class Head,class... Tail> struct Last<pack<Head,Tail...>>{ typedef typename Last<Tail...>::type type; }; template<class Tail> struct Last<Tail>{ typedef Tail type; }; template<class... Pack> using Last_t=typename Last<Pack...>::type; // Popfront template<class...> struct Popfront; template<class Head,class... Tail> struct Popfront<Head,Tail...>{ typedef pack<Tail...> type; }; template<class Head,class... Tail> struct Popfront<pack<Head,Tail...>>{ typedef pack<Tail...> type; }; template<class... Pack> using Popfront_t=typename Popfront<Pack...>::type; // Popback template<class...> struct Popback; template<class Head,class... Tail> struct Popback<Head,Tail...>{ typedef Concat_t<Head,typename Popback<Tail...>::type> type; }; template<class Head,class... Tail> struct Popback< pack<Head,Tail...> >{ typedef Concat_t<Head,typename Popback<Tail...>::type> type; }; template<class Tail> struct Popback<Tail>{ typedef pack<> type; }; template<class... Pack> using Popback_t=typename Popback<Pack...>::type; // Reverse template<class... Args> struct Reverse{ typedef Concat_t< Last_t<Args...>,typename Reverse< Popback_t<Args...> >::type > type; }; template<class... Args> struct Reverse<pack<Args...>>{ typedef Concat_t< Last_t<Args...>,typename Reverse< Popback_t<Args...> >::type > type; }; template<> struct Reverse<pack<>>{ typedef pack<> type; }; template<class... Args> using Reverse_t=typename Reverse<Args...>::type; // PartialHead template<std::size_t,class...> struct PartialHead; template<std::size_t N,class Head,class... Args> struct PartialHead<N,Head,Args...>{ typedef Concat_t<Head,typename PartialHead<N-1,Args...>::type> type; }; template<std::size_t N,class Head,class... Args> struct PartialHead<N,pack<Head,Args...>>{ typedef Concat_t<Head,typename PartialHead<N-1,Args...>::type> type; }; template<class Tail,class... Args> struct PartialHead<1,Tail,Args...>{ typedef Tail type; }; template<std::size_t N,class... Pack> using PartialHead_t=typename PartialHead<N,Pack...>::type; // PartialTail template<class... Arg> struct Apply; template<class Head,class... Tail> struct Apply<Head,Tail...>{ typedef Concat_t<Head,typename Apply<Tail...>::type> type; }; template<class Tail> struct Apply<Tail>{ typedef Tail type; }; template<> struct Apply<>{ typedef pack<> type; }; template<std::size_t N,class Head,class... Tail> struct PartialTail{ typedef typename PartialTail<N-1,Tail...>::type type; }; template<std::size_t N,class Head,class... Tail> struct PartialTail<N,pack<Head,Tail...>>{ typedef typename PartialTail<N-1,Tail...>::type type; }; template<class Head,class... Tail> struct PartialTail<0,Head,Tail...>{ typedef Concat_t<Head,typename Apply<Tail...>::type> type; }; template<std::size_t N,class... Args> using PartialTail_t=typename PartialTail<N,Args...>::type; // At template<std::size_t index,class...> struct At; template<std::size_t index,class Head,class... Tail> struct At<index,Head,Tail...>{ typedef typename At<index-1,Tail...>::type type; }; template<std::size_t index,class Head,class... Tail> struct At<index,pack<Head,Tail...>>{ typedef typename At<index-1,Tail...>::type type; }; template<class Target,class... Tail> struct At<0,Target,Tail...>{ typedef Target type; }; template<std::size_t index,class... Pack> using At_t=typename At<index,Pack...>::type;
改善版
patialモノはまあまあ便利なのではないかと思う。
typedef pack<int,char,float,double,int> test_type; PartialHead_t<3,test_type>; // int char float PartialTail_t<3,test_type>; // float double int
型のサイズごとのクイックソートを実装しようかと目論んだが、面倒になってしまったので誰か適当にやっといて欲しい。
template<class...> struct Left{}; template<class...> struct Right{}; template<int,bool,class,class...> struct QSort_Skip_Counter; template<int N,class Pivot,class Head,class... Tail> struct QSort_Skip_Counter<N,false,Pivot,Head,Tail...>{ static constexpr int value=QSort_Skip_Counter<N+1,(sizeof(Head)<sizeof(Pivot)),Pivot,Tail...>::value; }; template<int N,class Pivot,class Tail> struct QSort_Skip_Counter<N,false,Pivot,Tail>{ static constexpr int value=N-1; }; template<std::size_t N,class Pivot,class... Tail> struct QSort_Skip_Counter<N,true,Pivot,Tail...>{ static constexpr int value=0; }; template<bool,class,class,class...> struct QSort_Skip_impl; template<class Pivot,class Head,class... Tail> struct QSort_Skip_impl<false,Pivot,Head,Tail...>{ typedef typename QSort_Skip_impl<( sizeof(Head)<sizeof(Pivot) ),Pivot,Tail...>::type type; static constexpr std::size_t value=QSort_Skip_Counter<0,(sizeof(Head)<sizeof(Pivot)),Pivot,Tail... >::value; }; template<class Pivot,class Head,class... Tail> struct QSort_Skip_impl<true,Pivot,Head,Tail...>{ typedef Head type; static constexpr std::size_t value=QSort_Skip_Counter<0,(sizeof(Head)<sizeof(Pivot)),Pivot,Tail... >::value; }; template<class...> struct QSort_Skip; template<class Pivot,class Head,class... Tail> struct QSort_Skip<Pivot,Right<Head,Tail...>>{ typedef typename QSort_Skip_impl< (sizeof(Head)<sizeof(Pivot)),Pivot,Head,Tail... >::type type; static constexpr std::size_t value=QSort_Skip_impl< (sizeof(Head)<sizeof(Pivot)),Pivot,Head,Tail... >::value; }; template<class Pivot,class Head,class... Tail> struct QSort_Skip<Pivot,Left<Head,Tail...>>{ typedef typename QSort_Skip_impl< (sizeof(Head)>sizeof(Pivot)),Pivot,Head,Tail... >::type type; static constexpr std::size_t value=QSort_Skip_impl< (sizeof(Head)>sizeof(Pivot)),Pivot,Head,Tail... >::value; }; template<bool,class,class,class,std::size_t,std::size_t> struct Swap_Apply; template<class Args...,class L,class R,std::size_t L_index,std::size_t R_index> struct Swap_Apply<false,pack<Args...>,L,R,L_index,R_index>{ /*typedef left_pack; typedef right_pack; typedef All_pack;*/ static constexpr bool condition=false; }; template<class... Args,class L,class R> struct Swap_Apply<true,pack<Args...>,L,R,L_index,R_index>{ private: typedef Concat_t<PartialHead_t<L_index-1,Args...>,L> left_pack_tmp; typedef Concat_t<PartialHead_t<R_index-1,Args...>,R> right_pack_tmp; public: typedef Concat_t<left_pack_tmp,PartialHead_t<L_index,Args...>> left_pack; typedef Concat_t<left_pack_tmp,PartialTail_t<R_index,Args...>> right_pack; typedef Concat_t<left_pack,right_pack> All_pack; }; template<class...> struct QSort; template<class Head,class... Tail> struct QSort<pack<Head,Tail...>>{ private: typedef pack<Head,Tail...> All_t; typedef At_t<(sizeof...(Tail)+1)/2,Head,Tail...> pivot_type; typedef typename QSort_Skip<pivot_type,Right<Head,Tail...>>::type skiped_left; typedef typename QSort_Skip<pivot_type,Left<Head,Tail...>>::type skiped_right; static constexpr std::size_t skiped_left_value=QSort_Skip<pivot_type,Right<Head,Tail...>>::value; static constexpr std::size_t skiped_right_value=QSort_Skip<pivot_type,Left<Head,Tail...>>::value; typedef Swap_Apply<( skiped_left_value >= skip_righted_value ),All_t,skiped_left,skiped_right,skiped_left_value,skiped_right_value>::type type; }; template<class... Pack> using QSort_t=typename QSort<Pack...>::type; template<class T> struct type_index{ explicit type_index()noexcept{std::cout<< boost::typeindex::type_id<T>().pretty_name() <<std::endl;} };
恐らく愚直に実装しようとしているから面倒なのだと思うのだが、何か面倒でない方法はないだろうか。
※追記
一つに適用するものと、全てに適用するメタ関数は、それぞれタグごとに処理を切り替えられるよう、xxxerとして新たに定義した。
以下のように使える。
#include<srook/mpl/variadic_player.hpp> #include<boost/type_index.hpp> #include<cstdio> #include<tuple> int main() { using namespace boost::typeindex; using namespace srook::mpl; using TestType=pack<int,int,int,int,char,char,char,char>; std::printf("%s\n%s\n%s\n%s\n", type_id< Transfer_t<std::tuple,Eraser_t<variadic_tag::Single,int,TestType>> >().pretty_name().c_str(), type_id< Transfer_t<std::tuple,Eraser_t<variadic_tag::All,int,TestType>> >().pretty_name().c_str(), type_id< Transfer_t<std::tuple,Replacer_t<variadic_tag::Single,int,char,TestType>> >().pretty_name().c_str(), type_id< Transfer_t<std::tuple,Replacer_t<variadic_tag::All,int,char,TestType>> >().pretty_name().c_str()); }
std::__1::tuple<int, int, int, char, char, char, char> std::__1::tuple<char, char, char, char> std::__1::tuple<char, int, int, int, char, char, char, char> std::__1::tuple<char, char, char, char, char, char, char, char>