rotate.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include <vector>
  2. #include <cstdlib>
  3. #include <boost/preprocessor.hpp>
  4. template <typename T, typename I, I T::*mem>
  5. struct access {
  6. using value_type = I;
  7. using access_type = T;
  8. value_type& get(access_type& t) const { return t.*mem; }
  9. value_type const& get(access_type const& t) const { return t.*mem; }
  10. };
  11. template <typename T, typename...Members>
  12. class rotate;
  13. template <typename T, typename...Members> class proxy;
  14. template <typename T, typename Member>
  15. class rotate<T, Member> {
  16. public:
  17. using value_type = typename Member::value_type;
  18. using data_type = std::vector<value_type>;
  19. value_type& get(size_t n, Member) { return rotated_.at(n); }
  20. value_type const& get(size_t n, Member) const { return rotated_.at(n); }
  21. data_type const& get(Member) const { return rotated_; }
  22. protected:
  23. void push_back(T const& t) {
  24. rotated_.push_back(Member().get(t));
  25. }
  26. private:
  27. data_type rotated_;
  28. };
  29. template <typename T, typename Member0, typename...Members>
  30. class rotate<T, Member0, Members...> : public rotate<T, Member0>, public rotate<T, Members...> {
  31. public:
  32. proxy<T, Member0, Members...> get(size_t n);
  33. void push_back(T const& t) {
  34. rotate<T, Member0>::push_back(t);
  35. rotate<T, Members...>::push_back(t);
  36. }
  37. using rotate<T, Member0>::get;
  38. using rotate<T, Members...>::get;
  39. };
  40. #define PROXY_ELEMENT(T, elem) decltype(T::elem)& elem
  41. #define PROXY_MEMBER(r, T, elem) PROXY_ELEMENT(T, elem);
  42. #define PROXY_CONSTR(r, T, elem) BOOST_PP_CAT(PROXY_ELEMENT(T, elem),_),
  43. #define PROXY_INIT(r, T, elem) elem(BOOST_PP_CAT(elem,_)),
  44. #define PROXY_SET(r, t, elem) t.elem = elem;
  45. #define proxy_t(T, mseq) proxy<T BOOST_PP_SEQ_FOR_EACH(ROTATE_ACCESS, T, mseq)>
  46. #define ROTATE_PROXY(T, mseq) \
  47. template<> class proxy_t(T, mseq) { \
  48. public: \
  49. proxy(BOOST_PP_SEQ_FOR_EACH(PROXY_CONSTR, T, mseq) bool) \
  50. : BOOST_PP_SEQ_FOR_EACH(PROXY_INIT, T, mseq) dummy(false) {} \
  51. \
  52. explicit operator T() const { \
  53. T t; \
  54. BOOST_PP_SEQ_FOR_EACH(PROXY_SET, t, mseq) \
  55. return t; \
  56. } \
  57. \
  58. BOOST_PP_SEQ_FOR_EACH(PROXY_MEMBER, T, mseq) \
  59. bool dummy; \
  60. }
  61. #define ROTATE_ACCESS(r, T, elem) ,access_t(T, elem)
  62. #define PROXY_ASSIGN(r, T, elem) rotate<T, access_t(T, elem)>::get(n, access_t(T, elem)()),
  63. #define rotate_t(T, mseq) rotate<T BOOST_PP_SEQ_FOR_EACH(ROTATE_ACCESS, T, mseq)>
  64. #define access_t(T, M) access<T, decltype(T::M), &T::M>
  65. //#define DEFINE_ROTATE_NAME(name, T, mseq) \
  66. // using name = rotate_t(T, mseq); \
  67. // ROTATE_PROXY(T, mseq); \
  68. // template <typename T, typename M0, typename...Ms> \
  69. // proxy<T, M0, Ms...> rotate<T, M0, Ms...>::get(size_t n) { \
  70. // return proxy<T, M0, Ms...>{BOOST_PP_SEQ_FOR_EACH(PROXY_ASSIGN, T, mseq) false}; \
  71. // }
  72. #define DEFINE_ROTATE_NAME(name, T, mseq) \
  73. ROTATE_PROXY(T, mseq); \
  74. class name : public rotate_t(T, mseq) { \
  75. public:\
  76. proxy_t(T, mseq) get(size_t n) { \
  77. return proxy_t(T, mseq){BOOST_PP_SEQ_FOR_EACH(PROXY_ASSIGN, T, mseq) false}; \
  78. } \
  79. using rotate_t(T, mseq)::get; \
  80. }
  81. #define DEFINE_ROTATE(T, mseq) DEFINE_ROTATE_NAME(T##_rotate, T, mseq)
  82. //#include <iostream>
  83. //
  84. //struct particle {
  85. // int x, y, dx, dy;
  86. // char color;
  87. //};
  88. //
  89. //DEFINE_ROTATE(particle, (color)(x)(y)(dx)(dy))
  90. //
  91. //int main(int argc, char const *argv[]) {
  92. // (void) argc;
  93. // (void) argv;
  94. // particle p{0, 0, 0, 0, 0};
  95. // particle_rotate pr;
  96. // pr.push_back(p);
  97. //
  98. // {
  99. // proxy<particle> pp = pr.get(0);
  100. // pp.x = 5;
  101. // }
  102. //
  103. // {
  104. // proxy<particle> pp = pr.get(0);
  105. // std::cout << pp.x << std::endl;
  106. // particle copy = particle(pp);
  107. // std::cout << copy.x << std::endl;
  108. // }
  109. //
  110. // return 0;
  111. //}