|
|
@@ -0,0 +1,132 @@
|
|
|
+#include <vector>
|
|
|
+#include <cstdlib>
|
|
|
+#include <boost/preprocessor.hpp>
|
|
|
+
|
|
|
+template <typename T, typename I, I T::*mem>
|
|
|
+struct access {
|
|
|
+ using value_type = I;
|
|
|
+ using access_type = T;
|
|
|
+
|
|
|
+ value_type& get(access_type& t) const { return t.*mem; }
|
|
|
+ value_type const& get(access_type const& t) const { return t.*mem; }
|
|
|
+};
|
|
|
+
|
|
|
+template <typename T, typename...Members>
|
|
|
+class rotate;
|
|
|
+
|
|
|
+template <typename T, typename...Members> class proxy;
|
|
|
+
|
|
|
+template <typename T, typename Member>
|
|
|
+class rotate<T, Member> {
|
|
|
+public:
|
|
|
+ using value_type = typename Member::value_type;
|
|
|
+ using data_type = std::vector<value_type>;
|
|
|
+
|
|
|
+ value_type& get(size_t n, Member) { return rotated_.at(n); }
|
|
|
+ value_type const& get(size_t n, Member) const { return rotated_.at(n); }
|
|
|
+
|
|
|
+ data_type const& get(Member) const { return rotated_; }
|
|
|
+
|
|
|
+protected:
|
|
|
+ void push_back(T const& t) {
|
|
|
+ rotated_.push_back(Member().get(t));
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ data_type rotated_;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename T, typename Member0, typename...Members>
|
|
|
+class rotate<T, Member0, Members...> : public rotate<T, Member0>, public rotate<T, Members...> {
|
|
|
+public:
|
|
|
+ proxy<T, Member0, Members...> get(size_t n);
|
|
|
+
|
|
|
+ void push_back(T const& t) {
|
|
|
+ rotate<T, Member0>::push_back(t);
|
|
|
+ rotate<T, Members...>::push_back(t);
|
|
|
+ }
|
|
|
+
|
|
|
+ using rotate<T, Member0>::get;
|
|
|
+ using rotate<T, Members...>::get;
|
|
|
+};
|
|
|
+
|
|
|
+#define PROXY_ELEMENT(T, elem) decltype(T::elem)& elem
|
|
|
+#define PROXY_MEMBER(r, T, elem) PROXY_ELEMENT(T, elem);
|
|
|
+#define PROXY_CONSTR(r, T, elem) BOOST_PP_CAT(PROXY_ELEMENT(T, elem),_),
|
|
|
+#define PROXY_INIT(r, T, elem) elem(BOOST_PP_CAT(elem,_)),
|
|
|
+#define PROXY_SET(r, t, elem) t.elem = elem;
|
|
|
+
|
|
|
+#define proxy_t(T, mseq) proxy<T BOOST_PP_SEQ_FOR_EACH(ROTATE_ACCESS, T, mseq)>
|
|
|
+
|
|
|
+#define ROTATE_PROXY(T, mseq) \
|
|
|
+ template<> class proxy_t(T, mseq) { \
|
|
|
+ public: \
|
|
|
+ proxy(BOOST_PP_SEQ_FOR_EACH(PROXY_CONSTR, T, mseq) bool) \
|
|
|
+ : BOOST_PP_SEQ_FOR_EACH(PROXY_INIT, T, mseq) dummy(false) {} \
|
|
|
+ \
|
|
|
+ explicit operator T() const { \
|
|
|
+ T t; \
|
|
|
+ BOOST_PP_SEQ_FOR_EACH(PROXY_SET, t, mseq) \
|
|
|
+ return t; \
|
|
|
+ } \
|
|
|
+ \
|
|
|
+ BOOST_PP_SEQ_FOR_EACH(PROXY_MEMBER, T, mseq) \
|
|
|
+ bool dummy; \
|
|
|
+ }
|
|
|
+
|
|
|
+#define ROTATE_ACCESS(r, T, elem) ,access_t(T, elem)
|
|
|
+#define PROXY_ASSIGN(r, T, elem) rotate<T, access_t(T, elem)>::get(n, access_t(T, elem)()),
|
|
|
+
|
|
|
+#define rotate_t(T, mseq) rotate<T BOOST_PP_SEQ_FOR_EACH(ROTATE_ACCESS, T, mseq)>
|
|
|
+#define access_t(T, M) access<T, decltype(T::M), &T::M>
|
|
|
+
|
|
|
+//#define DEFINE_ROTATE_NAME(name, T, mseq) \
|
|
|
+// using name = rotate_t(T, mseq); \
|
|
|
+// ROTATE_PROXY(T, mseq); \
|
|
|
+// template <typename T, typename M0, typename...Ms> \
|
|
|
+// proxy<T, M0, Ms...> rotate<T, M0, Ms...>::get(size_t n) { \
|
|
|
+// return proxy<T, M0, Ms...>{BOOST_PP_SEQ_FOR_EACH(PROXY_ASSIGN, T, mseq) false}; \
|
|
|
+// }
|
|
|
+
|
|
|
+#define DEFINE_ROTATE_NAME(name, T, mseq) \
|
|
|
+ ROTATE_PROXY(T, mseq); \
|
|
|
+ class name : public rotate_t(T, mseq) { \
|
|
|
+ public:\
|
|
|
+ proxy_t(T, mseq) get(size_t n) { \
|
|
|
+ return proxy_t(T, mseq){BOOST_PP_SEQ_FOR_EACH(PROXY_ASSIGN, T, mseq) false}; \
|
|
|
+ } \
|
|
|
+ using rotate_t(T, mseq)::get; \
|
|
|
+ }
|
|
|
+
|
|
|
+#define DEFINE_ROTATE(T, mseq) DEFINE_ROTATE_NAME(T##_rotate, T, mseq)
|
|
|
+
|
|
|
+//#include <iostream>
|
|
|
+//
|
|
|
+//struct particle {
|
|
|
+// int x, y, dx, dy;
|
|
|
+// char color;
|
|
|
+//};
|
|
|
+//
|
|
|
+//DEFINE_ROTATE(particle, (color)(x)(y)(dx)(dy))
|
|
|
+//
|
|
|
+//int main(int argc, char const *argv[]) {
|
|
|
+// (void) argc;
|
|
|
+// (void) argv;
|
|
|
+// particle p{0, 0, 0, 0, 0};
|
|
|
+// particle_rotate pr;
|
|
|
+// pr.push_back(p);
|
|
|
+//
|
|
|
+// {
|
|
|
+// proxy<particle> pp = pr.get(0);
|
|
|
+// pp.x = 5;
|
|
|
+// }
|
|
|
+//
|
|
|
+// {
|
|
|
+// proxy<particle> pp = pr.get(0);
|
|
|
+// std::cout << pp.x << std::endl;
|
|
|
+// particle copy = particle(pp);
|
|
|
+// std::cout << copy.x << std::endl;
|
|
|
+// }
|
|
|
+//
|
|
|
+// return 0;
|
|
|
+//}
|