Advertisement
Guest User

multi_iterator

a guest
Jul 31st, 2013
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.46 KB | None | 0 0
  1. #include <iostream>
  2. #include <tuple>
  3. #include <iterator>
  4. #include <type_traits>
  5.  
  6. /*
  7.  * Obojsmerny iterator ktory zoskupuje rozne iteratory z roznych kontainerov
  8.  */
  9. namespace abu{
  10.    
  11. template <class... Is>
  12. class multi_iterator : public std::tuple<Is...>{
  13.     public:
  14.         using base = std::tuple<Is...>;
  15.         using tuple = base;    
  16.         template<size_t N>
  17.         using iterator_n = typename std::tuple_element<N, tuple>::type;
  18.        
  19.         using iterator_category = std::bidirectional_iterator_tag;
  20.         using value_type = multi_iterator;
  21.         using reference = value_type&;
  22.         using pointer = value_type*;
  23.         using const_reference = const reference;
  24.         using const_pointer = const pointer;
  25.    
  26.     private:
  27.         template<class Tuple, size_t N>
  28.         struct Move{
  29.             static inline void next(Tuple& iters){
  30.                 ++(std::get<N>(iters));
  31.                 Move<Tuple, N-1>::next(iters);
  32.             }
  33.            
  34.             static inline void prev(Tuple& iters){
  35.                 --(std::get<N>(iters));
  36.                 Move<Tuple, N-1>::prev(iters);
  37.             }
  38.         };
  39.  
  40.         template<class Tuple>
  41.         struct Move<Tuple, 0>{
  42.             static inline void next(Tuple& iters){++(std::get<0>(iters));}
  43.             static inline void prev(Tuple& iters){--(std::get<0>(iters));}
  44.         };
  45.    
  46.         void next(){Move<tuple, std::tuple_size<tuple>::value-1>::next(*this);}
  47.         void prev(){Move<tuple, std::tuple_size<tuple>::value-1>::prev(*this);}
  48.        
  49.     public:    
  50.         multi_iterator& operator++(){this->next();return *this;}
  51.         multi_iterator& operator++(int){this->next();return *this;}
  52.         multi_iterator& operator--(){this->prev();return *this;}
  53.         multi_iterator& operator--(int){this->prev();return *this;}
  54.        
  55.         template<size_t N>
  56.         iterator_n<N>& get(){return std::get<N>(*this);}
  57.        
  58.         template<size_t N>
  59.         const iterator_n<N>& get()const{return std::get<N>(*this);}
  60.        
  61.         template<size_t N>
  62.         const iterator_n<N>& cget()const{return std::get<N>(*this);}
  63.        
  64.         reference operator*(){return *this;}
  65.         const_reference operator*()const{return *this;}
  66.        
  67.         multi_iterator(){}
  68.         multi_iterator(tuple&& t):base(std::move(t)){} 
  69.         multi_iterator(const tuple& t):base(t){}   
  70.         multi_iterator(Is... is):base(is...){}     
  71. };
  72.  
  73. template <class... Is>
  74. multi_iterator<Is...> make_multi_iterator(Is... is){return multi_iterator<Is...>(is...);}
  75. template <class... Is>
  76. multi_iterator<Is...> make_multi_iterator(const std::tuple<Is...>& tuple){return multi_iterator<Is...>(tuple);}
  77. template <class... Is>
  78. multi_iterator<Is...> make_multi_iterator(std::tuple<Is...>&& tuple){return multi_iterator<Is...>(std::move(tuple));}
  79.  
  80. /*
  81.  * pair ktory obsahuje iteratory, na kontainer <first, second) a tvari sa ako container (ma metody begin a end)
  82.  */
  83. template <class Iterator>
  84. struct range : public std::pair<Iterator, Iterator>{
  85.     public:
  86.         using pair = std::pair<Iterator, Iterator>;
  87.         using iterator = Iterator;
  88.  
  89.     public:
  90.         iterator& begin(){return this->pair::first;}
  91.         const iterator& begin()const{return this->pair::first;}
  92.         const iterator& cbegin()const{return this->pair::first;}
  93.        
  94.         iterator& end(){return this->pair::second;}
  95.         const iterator& end()const{return this->pair::second;}
  96.         const iterator& cend()const{return this->pair::second;}
  97.  
  98.         range(const range& ) = default;
  99.         range(const pair& p):pair(p){}
  100.         range(iterator b, iterator e):pair(b, e){}
  101. };
  102.  
  103. template <class Iterator>
  104. range<Iterator> make_range(Iterator b, Iterator e){return range<Iterator>(b, e);}
  105. template <class Iterator>
  106. range<Iterator> make_range(const std::pair<Iterator, Iterator>& pair){return range<Iterator>(pair);}
  107.  
  108. /*
  109.  *
  110.  */
  111. template <class... Is>
  112. struct multi_iterator_range : public range<multi_iterator<Is...>>{
  113.     using base = range<multi_iterator<Is...>>;
  114.     using pair = typename base::pair;
  115.     using iterator = typename base::iterator;
  116.     using tuple = typename base::iterator::tuple;
  117.     template<size_t N>
  118.     using iterator_n = multi_iterator<Is...>::iterator_n<N>;
  119.    
  120.     using base::begin;
  121.     using base::cbegin;
  122.     using base::end;
  123.     using base::cend;
  124.    
  125.     template<size_t N>iterator_n<N>& begin(){return std::get<N>(this->begin());}
  126.     template<size_t N>const iterator_n<N>& begin()const{return std::get<N>(this->begin());}
  127.     template<size_t N>const iterator_n<N>& cbegin()const{return std::get<N>(this->begin());}
  128.    
  129.     template<size_t N>iterator_n<N>& end(){return std::get<N>(this->end());}
  130.     template<size_t N>const iterator_n<N>& end()const{return std::get<N>(this->end());}
  131.     template<size_t N>const iterator_n<N>& cend()const{return std::get<N>(this->end());}
  132.    
  133.     multi_iterator_range(const multi_iterator_range& ) = default;
  134.     multi_iterator_range(const base& r):base(r){}
  135.     multi_iterator_range(const pair& p):base(p){}
  136.     multi_iterator_range(iterator b, iterator e):base(b, e){}
  137. };
  138.  
  139. template <class... Cs>
  140. auto make_multi_iterator_range(Cs&... cs) -> multi_iterator_range<decltype(std::begin(cs))...>{
  141.     return multi_iterator_range<decltype(std::begin(cs))...>(
  142.         make_multi_iterator(std::begin(cs)...),
  143.         make_multi_iterator(std::end(cs)...)
  144.     ); 
  145. }
  146. template <class... Is>
  147. multi_iterator_range<Is...> make_multi_iterator_range(const multi_iterator<Is...>& b, const multi_iterator<Is...>& e){
  148.     return {b, e};
  149. }
  150.  
  151. } /* namespace abu */
  152.  
  153. #include <vector>
  154. #include <list>
  155. #include <unordered_set>
  156. #include <algorithm>
  157.  
  158. int main(){
  159.    
  160.     std::vector<int> a{4, 3, 2, 1};
  161.     std::list<char> b{'a', 'b', 'c', 'd'};
  162.     std::unordered_set<std::string> c{"Boo", "Minsc", "Aladin", "Ehmm"};
  163.    
  164.     using namespace abu;
  165.     auto r = make_multi_iterator_range(a, b, c);
  166.    
  167.     for(auto i = r.begin();  i != r.end() ; ++i){
  168.         /*
  169.          * Toto je neefektivne lebo sa v podmienke porovnavaju vsetky iteratory
  170.          */
  171.         std::cout
  172.             << "["
  173.             << *i.get<0>()
  174.             << ", "
  175.             << *i.get<1>()
  176.             << ", "
  177.             << *i.get<2>()
  178.             << "]\n"
  179.         ;
  180.        
  181.     }
  182.     std::cout << "-------------------------------------------------------------------\n";
  183.     for(auto& i : make_multi_iterator_range(c, b, a)){
  184.         /*
  185.          * Toto je neefektivne lebo sa v podmienke porovnavaju vsetky iteratory
  186.          * i je iterator lebo multi_iterator::operator*() vracia (*this)  :)
  187.          */
  188.         std::cout
  189.             << "["
  190.             << *i.get<0>()
  191.             << ", "
  192.             << *i.get<1>()
  193.             << ", "
  194.             << *i.get<2>()
  195.             << "]\n"
  196.         ;
  197.        
  198.     }
  199.     std::cout << "-------------------------------------------------------------------\n";
  200.    
  201.     for(auto i = r.begin();  i.get<0>() != r.end<0>() ; ++i){
  202.         /*
  203.          * Staci porovnat 1 iterator
  204.          */
  205.         std::cout
  206.             << "["
  207.             << *i.get<0>()
  208.             << ", "
  209.             << *i.get<1>()
  210.             << ", "
  211.             << *i.get<2>()
  212.             << "]\n"
  213.         ;
  214.        
  215.     }
  216. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement