c++ - How to implement recursive "using"/extract template parameters -


so asked question deleted it, found interesting challenge.

they had weird type, , had run problem concat , range castable sequences not sequences (for obvious reasons)

template<unsigned... is> struct sequence{};      template<typename... is> struct concat{}; template<unsigned... is> struct concat<sequence<is...>> : public sequence<is...> {}; template<unsigned... is, unsigned... js, typename... rest> struct concat<sequence<is...>, sequence<js...>, rest...>    : concat<sequence<is..., js...>, rest...> {}; 

so figured it'd interesting challenge right, making same type.

so first pass @ concat ran unexpected problems...how on earth 1 extract template parameters sequences? ended using function below:

template <unsigned... is,unsigned... js> constexpr auto concat_results(sequence<is...>,sequence<js...>) -> sequence<is...,js...> {   return sequence<is...,js...>(); }   template <typename seq1,typename seq2> using concat = decltype(concat_results(seq1(),seq2())); 

bizarrely, think that's shortest way declare it, though little weird. however, concat_results useful (on references of sequences) , type can useful in other places. have better way that?

next range, did recursive struct helper:

template <unsigned n> struct nrange_helper {   using range = concat<typename nrange_helper<n-1>::range,sequence<n>>; };  template <> struct nrange_helper<0> {   using range = sequence<0>; };  template <unsigned n> using range = typename nrange_helper<n>::range; 

again, weird, works...but feel there should better way. got one?

note: please check out std::integer_sequence, specialization index_sequence , make_index_sequence , index_sequence_for facilities.

if want declare them yourself, use inner types:

template <typename, typename> struct concat;  template <unsigned... is, unsigned... js> struct concat<sequence<is...>,sequence<js...>> {     using type = sequence<is..., js...>; };  template <unsigned n> struct range {     using type = typename concat<typename range<n-1>::type, sequence<n>>::type; };  template <> struct range<0> { using type = sequence<0>; }; 

which can of course combined template aliases shorter final form:

 template <typename, typename> struct concath;  template <unsigned... is, unsigned... js> struct concath<sequence<is...>,sequence<js...>> {     using type = sequence<is..., js...>; };  template <typename l, typename r> using concat = typename concath<l, r>::type; 

and:

template <unsigned n> struct rangeh {     using type = concat<typename rangeh<n-1>::type, sequence<n>>; };  template <> struct rangeh<0> { using type = sequence<0>; };  template <unsigned n> using range = typename rangeh<n>::type; 

however, indeed, verbose. still, there little cruft here:

  • baseline declaration
  • specialization (to end recursion or limit "interesting" types)
  • alias declaration

on other hand it's written once.


Comments

Popular posts from this blog

php - regexp cyrillic filename not matches -

c# - OpenXML hanging while writing elements -

sql - Select Query has unexpected multiple records (MS Access) -