c++ - composing different types of make_pack_indices -
c++ - composing different types of make_pack_indices -
suppose:
make_pack_indices<start, end>::type
type pack_indices<start, start+1, start+2, ..., end-1>
make_reverse_indices<std::size_t size>::type
type pack_indices<size-1, size-2, ..., 2, 1, 0>
make_rotated_indices<size, shift>::type
type pack_indices<shift, shift+1, ..., size-1, 0, 1, 2, ..., shift-1>
make_alternating_indices<size, start, interval>::type
type pack_indices<start, start + interval, start + 2 * interval, ...>
until largest index less start
reached.
how carry out combination of these forms of make_indices through sort of composition like
compose<a, c, b, a..., d>::type,
where a,b,c,d
types (functors or whatever) representing above 4 make_indices
types? example,
a = make_pack_indices<1,4> b = make_reverse_indices<5> c = make_rotated_indices<5,2>
then
compose<b,c,a>::type
would be
pack_indices<4,3,2,1,0> -> pack_indices<2,1,0,4,3> -> pack_indices<1,0,4>
a simpler illustration that
compose <make_rotated_indices<10,2>, make_rotated_indices<10,4>>::type
would be
make_rotated_indices<10,6>::type.
here application. suppose have argument pack
('a', 3.14 , 5, "home", '!', 4.5, "car", 20, 0.5, 'b')
we can reverse using make_reverse_indices<10>, , can rotate left 3 using make_rotated_indices<10,3>. suppose want reverse pack followed rotating left 3. instead of manually doing 1 followed other, want define compose struct take make_reverse_indices<10> , make_rotated_indices<10,3> parameters , give desired result in 1 go, be
("car", 4.5, '!', "home", 5, 3.14, 'a', 'b', 0.5, 20)
i think (in above example) make_reverse_indices<10> , make_rotated_indices<10,3> need converted else. make_reverse_indices<10> gives 9,8,7,...,1,0. make_rotated_indices<10,3> (instead of giving 3,4,5,...9,0,1,2) needs turned function accepts parameter pack 9,8,7,...,1,0 , carry out effect of make_rotated_indices<10,3>, thereby giving 6,5,4,...0,9,8,7. thought i'm working on: define helper function extract indices rotated_indices<10,3>::type, turn parameter pack , apply make_rotated_indices<10,3> on parameter pack.
here code have, in case needs testing (the structs have been tested thoroughly):
#include <iostream> #include <string> #include <tuple> template<std::size_t...> struct pack_indices { using type = pack_indices; }; constexpr int positivemodulo(int i, int n) { homecoming (i % n + n) % n; } template<std::size_t start, std::size_t end, std::size_t... indices> struct make_indices : make_indices<start + 1, end, indices..., start> {}; template<std::size_t end, std::size_t... indices> struct make_indices<end, end, indices...> : pack_indices <indices...> {}; template<std::size_t size, std::size_t... indices> struct make_reverse_indices : make_reverse_indices<size - 1, indices..., size - 1> {}; template<std::size_t... indices> struct make_reverse_indices<0, indices...> : pack_indices<indices...> {}; template<std::size_t size, std::size_t shift, std::size_t shift_, std::size_t... indices> struct make_rotated_indices_helper : make_rotated_indices_helper<size, shift, shift_ + 1, indices..., positivemodulo(shift + shift_, size)> {}; template<std::size_t size, std::size_t shift, std::size_t...indices> struct make_rotated_indices_helper<size, shift, size, indices...> : pack_indices<indices...> {}; template<std::size_t size, std::size_t shift, std::size_t... indices> struct make_rotated_indices { using type = make_rotated_indices_helper<size, shift, 0, indices...>; }; template<std::size_t size, std::size_t start, std::size_t interval, std::size_t num_left, std::size_t... indices> struct make_alternating_indices_helper : make_alternating_indices_helper<size, start + interval, interval, num_left - 1, indices..., positivemodulo(start, size)> {}; template<std::size_t size, std::size_t start, std::size_t interval, std::size_t... indices> struct make_alternating_indices_helper<size, start, interval, 0, indices...> : pack_indices<indices...> {}; template<std::size_t size, std::size_t start, std::size_t interval, std::size_t... indices> struct make_alternating_indices { using type = make_alternating_indices_helper<size, start, interval, (size - 1) / interval + 1>; }; // testing namespace pack { template<typename last> void print(last && last) { std::cout << std::forward<last>(last) << std::endl; } template<typename first, typename... rest> void print(first && first, rest&&... rest) { std::cout << std::forward<first>(first) << ", "; print<rest...>(std::forward<rest>(rest)...); } } template<typename tuple, std::size_t... indices> void showvalueshelper(tuple&& tuple, const pack_indices<indices...>&) { pack::print(std::get<indices>(std::forward<tuple>(tuple))...); } template<std::size_t start, std::size_t end, typename... types> void showmiddlevalues(types && ...types) { const auto tuple = std::forward_as_tuple(std::forward<types>(types)...); const typename make_indices<start, end>::type indices; showvalueshelper (tuple, indices); } int main() { std::cout << "original argument pack: "; pack::print('a', 3.14, 5, "home", '!', 4.5, "car", 20, 0.5, 'b'); std::cout << "showmiddlevalues<2,7> = "; showmiddlevalues<2, 7>('a', 3.14, 5, "home", '!', 4.5, "car", 20, 0.5, 'b'); // 5, home, !, 4.5, auto }
one posible solution using simple recursion , binary concatenation:
template<typename lhs , typename rhs> struct concat; template<std::size_t... , std::size_t... js> struct concat<sequence<is...>,sequence<js...>> { using type = sequence<is...,js...>; }; template<typename... ss> struct multi_concat; template<typename head , typename... tail> struct multi_concat<head,tail...> { using type = typename concat<head,typename multi_concat<tail...>::type>::type; }; template<> struct multi_concat<> { using type = sequence<>; };
c++ templates c++11 recursion compose
Comments
Post a Comment