#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;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KCiNkZWZpbmUgUmV0dXJuKFJldCkgZGVjbHR5cGUgUmV0IHsgcmV0dXJuIFJldDsgfQoKdGVtcGxhdGUgPGludCBOVU1fTEVGVCwgaW50IFNISUZUPgpjbGFzcyByb3RhdGVfdHVwbGVfaGVscGVyIHsKICAgIHByaXZhdGU6CiAgICAgICAgc3RhdGljIGNvbnN0ZXhwciBpbnQgcG9zaXRpdmVNb2R1bG8gKGludCBpLCBpbnQgbikge3JldHVybiAoaSAlIG4gKyBuKSAlIG47fQogICAgICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUVVBMRT4KICAgICAgICBzdGF0aWMgY29uc3RleHByIGludCBzaGlmdCgpIHtyZXR1cm4gcG9zaXRpdmVNb2R1bG8gKFNISUZULCBzdGQ6OnR1cGxlX3NpemU8VFVQTEU+Ojp2YWx1ZSk7fQogICAgcHVibGljOgogICAgICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUVVBMRT4KICAgICAgICBjb25zdGV4cHIgYXV0byBvcGVyYXRvcigpIChjb25zdCBUVVBMRSYgdCkgY29uc3QKICAgICAgICAtPiBSZXR1cm4oKHN0ZDo6dHVwbGVfY2F0IChzdGQ6Om1ha2VfdHVwbGUgKHN0ZDo6Z2V0PHNoaWZ0PFRVUExFPigpPih0KSksIHJvdGF0ZV90dXBsZV9oZWxwZXI8TlVNX0xFRlQtMSwgU0hJRlQrMT4oKSh0KSkpKQp9OwoKdGVtcGxhdGUgPGludCBTSElGVD4KY2xhc3Mgcm90YXRlX3R1cGxlX2hlbHBlcjwwLCBTSElGVD4gewogICAgcHVibGljOgogICAgICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUVVBMRT4KICAgICAgICBjb25zdGV4cHIgc3RkOjp0dXBsZTw+IG9wZXJhdG9yKCkgKGNvbnN0IFRVUExFJiApIGNvbnN0IHtyZXR1cm4gc3RkOjp0dXBsZTw+KCk7fQp9OwoKdGVtcGxhdGUgPGludCBTSElGVD4Kc3RydWN0IHJvdGF0ZV90dXBsZSB7CiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVFVQTEU+CiAgICBjb25zdGV4cHIgYXV0byBvcGVyYXRvcigpIChjb25zdCBUVVBMRSYgdCkgY29uc3QgLT4gUmV0dXJuICgocm90YXRlX3R1cGxlX2hlbHBlcjxzdGQ6OnR1cGxlX3NpemU8VFVQTEU+Ojp2YWx1ZSwgU0hJRlQ+KCkodCkpKQp9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IE4sIHR5cGVuYW1lIEZ1bmN0b3I+IHN0cnVjdCBzZWxmX2NvbXBvc2VOCnsKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUPgogICAgY29uc3RleHByIGF1dG8gb3BlcmF0b3IgKCkgKFQgdCkgY29uc3QgLT4gUmV0dXJuKChzZWxmX2NvbXBvc2VOPE4gLSAxLCBGdW5jdG9yPigpKEZ1bmN0b3IoKSh0KSkpKQp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIEZ1bmN0b3I+IHN0cnVjdCBzZWxmX2NvbXBvc2VOPDB1LCBGdW5jdG9yPgp7CiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KICAgIGNvbnN0ZXhwciBUIG9wZXJhdG9yICgpIChUIHQpIGNvbnN0IHsgcmV0dXJuIHQ7IH0KfTsKCgojaWYgMSAvLyBOb3QgaW4gQysrMTEgLy8gbWFrZV9pbmRleF9zZXF1ZW5jZQojaW5jbHVkZSA8Y3N0ZGludD4KCnRlbXBsYXRlIDxzdGQ6OnNpemVfdC4uLj4gc3RydWN0IGluZGV4X3NlcXVlbmNlIHt9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IE4sIHN0ZDo6c2l6ZV90Li4uIElzPgpzdHJ1Y3QgbWFrZV9pbmRleF9zZXF1ZW5jZSA6IG1ha2VfaW5kZXhfc2VxdWVuY2U8TiAtIDEsIE4gLSAxLCBJcy4uLj4ge307Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QuLi4gSXM+CnN0cnVjdCBtYWtlX2luZGV4X3NlcXVlbmNlPDB1LCBJcy4uLj4gOiBpbmRleF9zZXF1ZW5jZTxJcy4uLj4ge307CgojZW5kaWYgLy8gbWFrZV9pbmRleF9zZXF1ZW5jZQoKbmFtZXNwYWNlIGRldGFpbCB7CnRlbXBsYXRlPHR5cGVuYW1lIFR1cGxlLCBzdGQ6OnNpemVfdC4uLiBJcz4Kdm9pZCBwcmludF90dXBsZShzdGQ6Om9zdHJlYW0mIG9zLCBUdXBsZSBjb25zdCYgdCwgaW5kZXhfc2VxdWVuY2U8SXMuLi4+KXsKCiAgICBpbnQgZHVtbXlbXSA9IHswLCAodm9pZChvcyA8PCAoSXMgPT0gMD8gIiIgOiAiLCAiKSA8PCBzdGQ6OmdldDxJcz4odCkpLCAwKS4uLn07CiAgICBzdGF0aWNfY2FzdDx2b2lkPihkdW1teSk7Cn0KCn0KCnRlbXBsYXRlIDx0eXBlbmFtZSAuLi5Ucz4Kc3RkOjpvc3RyZWFtJiBvcGVyYXRvciA8PCAoc3RkOjpvc3RyZWFtJiBvcywgY29uc3Qgc3RkOjp0dXBsZTxUcy4uLj4mIHQpCnsKICAgIG9zIDw8ICJ7IjsKICAgIGRldGFpbDo6cHJpbnRfdHVwbGUob3MsIHQsIG1ha2VfaW5kZXhfc2VxdWVuY2U8c2l6ZW9mLi4uKFRzKT4oKSk7CiAgICByZXR1cm4gb3MgPDwgIn0iOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVHVwbGU+CnZvaWQgcHJpbnQoY29uc3Qgc3RkOjpzdHJpbmcmIG5hbWUsIGNvbnN0IFR1cGxlJnQpCnsKICAgIHN0ZDo6Y291dCA8PCBuYW1lIDw8ICIgPSAiIDw8IHQgPDwgc3RkOjplbmRsOwp9CgppbnQgbWFpbigpIHsKICAgIHVzaW5nIHR1cGxlX3R5cGUgPSBzdGQ6OnR1cGxlPGludCwgc3RkOjpzdHJpbmcsIGRvdWJsZSwgY2hhciwgc3RkOjpzdHJpbmcsIGludCwgZG91YmxlLCBjaGFyPjsKICAgIGNvbnN0IHR1cGxlX3R5cGUgdCAoOCwgImhvdXNlIiwgMy4xNCwgJ2InLCAiYXBwbGUiLCA2LCAxLjUsICchJyk7CgogICAgcHJpbnQoInJvdDAiLCByb3RhdGVfdHVwbGU8MD4oKSh0KSk7CiAgICBwcmludCgicm90MSIsIHJvdGF0ZV90dXBsZTwxPigpKHQpKTsKICAgIHByaW50KCJyb3QyIiwgcm90YXRlX3R1cGxlPDI+KCkodCkpOwogICAgcHJpbnQoInJvdDMiLCByb3RhdGVfdHVwbGU8Mz4oKSh0KSk7CgogICAgcHJpbnQoInNlbGYwIiwgc2VsZl9jb21wb3NlTjwwdSwgcm90YXRlX3R1cGxlPDE+PigpKHQpKTsKICAgIHByaW50KCJzZWxmMSIsIHNlbGZfY29tcG9zZU48MXUsIHJvdGF0ZV90dXBsZTwxPj4oKSh0KSk7CiAgICBwcmludCgic2VsZjIiLCBzZWxmX2NvbXBvc2VOPDJ1LCByb3RhdGVfdHVwbGU8MT4+KCkodCkpOwogICAgcHJpbnQoInNlbGYzIiwgc2VsZl9jb21wb3NlTjwzdSwgcm90YXRlX3R1cGxlPDE+PigpKHQpKTsKCiAgICByZXR1cm4gMDsKfQo=
rot0 = {8, house, 3.14, b, apple, 6, 1.5, !}
rot1 = {house, 3.14, b, apple, 6, 1.5, !, 8}
rot2 = {3.14, b, apple, 6, 1.5, !, 8, house}
rot3 = {b, apple, 6, 1.5, !, 8, house, 3.14}
self0 = {8, house, 3.14, b, apple, 6, 1.5, !}
self1 = {house, 3.14, b, apple, 6, 1.5, !, 8}
self2 = {3.14, b, apple, 6, 1.5, !, 8, house}
self3 = {b, apple, 6, 1.5, !, 8, house, 3.14}