| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- #pragma once
- #include <vector>
- #include <cstdlib>
- #include <boost/preprocessor/seq/for_each.hpp>
- namespace data {
- 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>;
-
- 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 <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);
- template <typename...Proxied> proxy<T, Proxied...> getp(size_t n);
- inline 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(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<T, rotate_members(T, mseq)>
- #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<T, access_t(T, elem)>::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<T, rotate_members(T, mseq)>
- #define access_t(T, M) data::access<T, decltype(T::M), &T::M>
- //#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)
|