#pragma once #include #include #include namespace data { template 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 class rotate; template class proxy; template class rotate { public: using value_type = typename Member::value_type; using data_type = std::vector; inline value_type& get(size_t n, Member) { return rotated_.at(n); } inline value_type const& get(size_t n, Member) const { return rotated_.at(n); } inline 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 class rotate : public rotate, public rotate { public: proxy get(size_t n); template proxy getp(size_t n); inline void push_back(T const& t) { rotate::push_back(t); rotate::push_back(t); } using rotate::get; using rotate::get; }; #define PROXY_ELEMENT(T, elem) decltype(T::elem)& elem #define PROXY_MEMBER(r, T, elem) PROXY_ELEMENT(T, elem); #define PROXY_CONSTR(T, elem) BOOST_PP_CAT(PROXY_ELEMENT(T, elem),_) #define PROXY_CONSTR_J(r, T, elem) , PROXY_CONSTR(T, elem) #define PROXY_INIT(T, elem) elem(BOOST_PP_CAT(elem,_)) #define PROXY_INIT_J(r, T, elem) , PROXY_INIT(T, elem) #define PROXY_SET(r, t, elem) t.elem = elem; #define PROXY_RSET(r, t, elem) elem = t.elem; #define proxy_t(T, mseq) proxy #define ROTATE_PROXY(T, mseq) \ template<> class proxy_t(T, mseq) { \ public: \ proxy(PROXY_CONSTR(T, BOOST_PP_SEQ_HEAD(mseq)) \ BOOST_PP_SEQ_FOR_EACH(PROXY_CONSTR_J, T, BOOST_PP_SEQ_TAIL(mseq))) \ : PROXY_INIT(T, BOOST_PP_SEQ_HEAD(mseq)) \ BOOST_PP_SEQ_FOR_EACH(PROXY_INIT_J, T, BOOST_PP_SEQ_TAIL(mseq)) \ { \ } \ \ proxy & operator=( T const & obj ) { \ BOOST_PP_SEQ_FOR_EACH(PROXY_RSET, obj, mseq) \ return *this; \ } \ \ 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) \ } #define ROTATE_ACCESS(T, elem) access_t(T, elem) #define ROTATE_ACCESS_J(r, T, elem) ,ROTATE_ACCESS(T, elem) #define PROXY_ASSIGN(T, elem) rotate::get(n, access_t(T, elem)()) #define PROXY_ASSIGN_J(r, T, elem) ,PROXY_ASSIGN(T, elem) #define rotate_members(T, mseq) ROTATE_ACCESS(T, BOOST_PP_SEQ_HEAD(mseq)) \ BOOST_PP_SEQ_FOR_EACH(ROTATE_ACCESS_J, T, BOOST_PP_SEQ_TAIL(mseq)) #define rotate_t(T, mseq) rotate #define access_t(T, M) data::access //#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){ \ // PROXY_ASSIGN(T, BOOST_PP_SEQ_HEAD(mseq)) \ // BOOST_PP_SEQ_FOR_EACH(PROXY_ASSIGN_J, T, BOOST_PP_SEQ_TAIL(mseq)) \ // }; \ // } \ // using rotate_t(T, mseq)::get; \ // } #define DEFINE_ROTATE_NAME(name, T, mseq) \ ROTATE_PROXY(T, mseq); \ using name##_proxy = proxy_t(T, mseq); \ template <> \ proxy_t(T, mseq) rotate_t(T, mseq)::get(size_t n) { \ return proxy_t(T, mseq){ \ PROXY_ASSIGN(T, BOOST_PP_SEQ_HEAD(mseq)) \ BOOST_PP_SEQ_FOR_EACH(PROXY_ASSIGN_J, T, BOOST_PP_SEQ_TAIL(mseq)) \ }; \ } \ using name = rotate_t(T, mseq) #define DEFINE_PROXY_NAME( name, T, mseq ) \ ROTATE_PROXY( T, mseq ); \ using name = proxy_t( T, mseq ); #define DEFINE_PROXY_CONVERSION(T, mseq1, mseq2) \ template <> \ template <> \ proxy_t(T, mseq2) rotate_t(T, mseq1)::getp(size_t n) { \ return proxy_t(T, mseq2){ \ PROXY_ASSIGN(T, BOOST_PP_SEQ_HEAD(mseq2)) \ BOOST_PP_SEQ_FOR_EACH(PROXY_ASSIGN_J, T, BOOST_PP_SEQ_TAIL(mseq2)) \ }; \ } #define DEFINE_ROTATE(T, mseq) \ using T##_proxy = proxy_t(T, mseq); \ DEFINE_ROTATE_NAME(T##_rotate, T, mseq)