rotate.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #pragma once
  2. #include <vector>
  3. #include <cstdlib>
  4. #include <boost/preprocessor/seq/for_each.hpp>
  5. namespace data {
  6. template <typename T, typename I, I T::*mem>
  7. struct access {
  8. using value_type = I;
  9. using access_type = T;
  10. value_type& get(access_type& t) const { return t.*mem; }
  11. value_type const& get(access_type const& t) const { return t.*mem; }
  12. };
  13. }
  14. template <typename T, typename...Members>
  15. class rotate;
  16. template <typename T, typename...Members> class proxy;
  17. template <typename T, typename Member>
  18. class rotate<T, Member> {
  19. public:
  20. using value_type = typename Member::value_type;
  21. using data_type = std::vector<value_type>;
  22. inline value_type& get(size_t n, Member) { return rotated_.at(n); }
  23. inline value_type const& get(size_t n, Member) const { return rotated_.at(n); }
  24. inline data_type const& get(Member) const { return rotated_; }
  25. protected:
  26. void push_back(T const& t) {
  27. rotated_.push_back(Member().get(t));
  28. }
  29. private:
  30. data_type rotated_;
  31. };
  32. template <typename T, typename Member0, typename...Members>
  33. class rotate<T, Member0, Members...> : public rotate<T, Member0>, public rotate<T, Members...> {
  34. public:
  35. proxy<T, Member0, Members...> get(size_t n);
  36. template <typename...Proxied> proxy<T, Proxied...> getp(size_t n);
  37. inline void push_back(T const& t) {
  38. rotate<T, Member0>::push_back(t);
  39. rotate<T, Members...>::push_back(t);
  40. }
  41. using rotate<T, Member0>::get;
  42. using rotate<T, Members...>::get;
  43. };
  44. #define PROXY_ELEMENT(T, elem) decltype(T::elem)& elem
  45. #define PROXY_MEMBER(r, T, elem) PROXY_ELEMENT(T, elem);
  46. #define PROXY_CONSTR(T, elem) BOOST_PP_CAT(PROXY_ELEMENT(T, elem),_)
  47. #define PROXY_CONSTR_J(r, T, elem) , PROXY_CONSTR(T, elem)
  48. #define PROXY_INIT(T, elem) elem(BOOST_PP_CAT(elem,_))
  49. #define PROXY_INIT_J(r, T, elem) , PROXY_INIT(T, elem)
  50. #define PROXY_SET(r, t, elem) t.elem = elem;
  51. #define PROXY_RSET(r, t, elem) elem = t.elem;
  52. #define proxy_t(T, mseq) proxy<T, rotate_members(T, mseq)>
  53. #define ROTATE_PROXY(T, mseq) \
  54. template<> class proxy_t(T, mseq) { \
  55. public: \
  56. proxy(PROXY_CONSTR(T, BOOST_PP_SEQ_HEAD(mseq)) \
  57. BOOST_PP_SEQ_FOR_EACH(PROXY_CONSTR_J, T, BOOST_PP_SEQ_TAIL(mseq))) \
  58. : PROXY_INIT(T, BOOST_PP_SEQ_HEAD(mseq)) \
  59. BOOST_PP_SEQ_FOR_EACH(PROXY_INIT_J, T, BOOST_PP_SEQ_TAIL(mseq)) \
  60. { \
  61. } \
  62. \
  63. proxy & operator=( T const & obj ) { \
  64. BOOST_PP_SEQ_FOR_EACH(PROXY_RSET, obj, mseq) \
  65. return *this; \
  66. } \
  67. \
  68. explicit operator T() const { \
  69. T t; \
  70. BOOST_PP_SEQ_FOR_EACH(PROXY_SET, t, mseq) \
  71. return t; \
  72. } \
  73. \
  74. BOOST_PP_SEQ_FOR_EACH(PROXY_MEMBER, T, mseq) \
  75. }
  76. #define ROTATE_ACCESS(T, elem) access_t(T, elem)
  77. #define ROTATE_ACCESS_J(r, T, elem) ,ROTATE_ACCESS(T, elem)
  78. #define PROXY_ASSIGN(T, elem) rotate<T, access_t(T, elem)>::get(n, access_t(T, elem)())
  79. #define PROXY_ASSIGN_J(r, T, elem) ,PROXY_ASSIGN(T, elem)
  80. #define rotate_members(T, mseq) ROTATE_ACCESS(T, BOOST_PP_SEQ_HEAD(mseq)) \
  81. BOOST_PP_SEQ_FOR_EACH(ROTATE_ACCESS_J, T, BOOST_PP_SEQ_TAIL(mseq))
  82. #define rotate_t(T, mseq) rotate<T, rotate_members(T, mseq)>
  83. #define access_t(T, M) data::access<T, decltype(T::M), &T::M>
  84. //#define DEFINE_ROTATE_NAME(name, T, mseq) \
  85. // ROTATE_PROXY(T, mseq); \
  86. // class name : public rotate_t(T, mseq) { \
  87. // public:\
  88. // proxy_t(T, mseq) get(size_t n) { \
  89. // return proxy_t(T, mseq){ \
  90. // PROXY_ASSIGN(T, BOOST_PP_SEQ_HEAD(mseq)) \
  91. // BOOST_PP_SEQ_FOR_EACH(PROXY_ASSIGN_J, T, BOOST_PP_SEQ_TAIL(mseq)) \
  92. // }; \
  93. // } \
  94. // using rotate_t(T, mseq)::get; \
  95. // }
  96. #define DEFINE_ROTATE_NAME(name, T, mseq) \
  97. ROTATE_PROXY(T, mseq); \
  98. using name##_proxy = proxy_t(T, mseq); \
  99. template <> \
  100. proxy_t(T, mseq) rotate_t(T, mseq)::get(size_t n) { \
  101. return proxy_t(T, mseq){ \
  102. PROXY_ASSIGN(T, BOOST_PP_SEQ_HEAD(mseq)) \
  103. BOOST_PP_SEQ_FOR_EACH(PROXY_ASSIGN_J, T, BOOST_PP_SEQ_TAIL(mseq)) \
  104. }; \
  105. } \
  106. using name = rotate_t(T, mseq)
  107. #define DEFINE_PROXY_NAME( name, T, mseq ) \
  108. ROTATE_PROXY( T, mseq ); \
  109. using name = proxy_t( T, mseq );
  110. #define DEFINE_PROXY_CONVERSION(T, mseq1, mseq2) \
  111. template <> \
  112. template <> \
  113. proxy_t(T, mseq2) rotate_t(T, mseq1)::getp(size_t n) { \
  114. return proxy_t(T, mseq2){ \
  115. PROXY_ASSIGN(T, BOOST_PP_SEQ_HEAD(mseq2)) \
  116. BOOST_PP_SEQ_FOR_EACH(PROXY_ASSIGN_J, T, BOOST_PP_SEQ_TAIL(mseq2)) \
  117. }; \
  118. }
  119. #define DEFINE_ROTATE(T, mseq) \
  120. using T##_proxy = proxy_t(T, mseq); \
  121. DEFINE_ROTATE_NAME(T##_rotate, T, mseq)