1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
#include <iostream>
#include <string>
#include <tuple>
template<std::size_t...>
struct pack_indices
{
using type = pack_indices;
};
constexpr int positiveModulo(int i, int n)
{
return (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, car
}
|