#include <iostream>
#include <string>
#include <functional>

#define Return(Ret) decltype Ret { return Ret; }

template <int NUM_LEFT, int SHIFT>
class rotate_tuple_helper {
    private:
        static constexpr int positiveModulo (int i, int n) {return (i % n + n) % n;}
        template <typename TUPLE>
        static constexpr int shift() {return positiveModulo (SHIFT, std::tuple_size<TUPLE>::value);}
    public:
        template <typename TUPLE>
        constexpr auto operator() (const TUPLE& t) const
        -> Return((std::tuple_cat (std::make_tuple (std::get<shift<TUPLE>()>(t)), rotate_tuple_helper<NUM_LEFT-1, SHIFT+1>()(t))))
};

template <int SHIFT>
class rotate_tuple_helper<0, SHIFT> {
    public:
        template <typename TUPLE>
        constexpr std::tuple<> operator() (const TUPLE& ) const {return std::tuple<>();}
};

template <int SHIFT>
struct rotate_tuple {
    template <typename TUPLE>
    constexpr auto operator() (const TUPLE& t) const -> Return ((rotate_tuple_helper<std::tuple_size<TUPLE>::value, SHIFT>()(t)))
};

template <std::size_t N, typename Functor> struct self_composeN
{
    template <typename T>
    constexpr auto operator () (T t) const -> Return((self_composeN<N - 1, Functor>()(Functor()(t))))
};

template <typename Functor> struct self_composeN<0u, Functor>
{
    template <typename T>
    constexpr T operator () (T t) const { return t; }
};


#if 1 // Not in C++11 // make_index_sequence
#include <cstdint>

template <std::size_t...> struct index_sequence {};

template <std::size_t N, std::size_t... Is>
struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> {};

template <std::size_t... Is>
struct make_index_sequence<0u, Is...> : index_sequence<Is...> {};

#endif // make_index_sequence

namespace detail {
template<typename Tuple, std::size_t... Is>
void print_tuple(std::ostream& os, Tuple const& t, index_sequence<Is...>){

    int dummy[] = {0, (void(os << (Is == 0? "" : ", ") << std::get<Is>(t)), 0)...};
    static_cast<void>(dummy);
}

}

template <typename ...Ts>
std::ostream& operator << (std::ostream& os, const std::tuple<Ts...>& t)
{
    os << "{";
    detail::print_tuple(os, t, make_index_sequence<sizeof...(Ts)>());
    return os << "}";
}

template <typename Tuple>
void print(const std::string& name, const Tuple&t)
{
    std::cout << name << " = " << t << std::endl;
}

int main() {
    using tuple_type = std::tuple<int, std::string, double, char, std::string, int, double, char>;
    const tuple_type t (8, "house", 3.14, 'b', "apple", 6, 1.5, '!');

    print("rot0", rotate_tuple<0>()(t));
    print("rot1", rotate_tuple<1>()(t));
    print("rot2", rotate_tuple<2>()(t));
    print("rot3", rotate_tuple<3>()(t));

    print("self0", self_composeN<0u, rotate_tuple<1>>()(t));
    print("self1", self_composeN<1u, rotate_tuple<1>>()(t));
    print("self2", self_composeN<2u, rotate_tuple<1>>()(t));
    print("self3", self_composeN<3u, rotate_tuple<1>>()(t));

    return 0;
}
