Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <tuple>
- #include <iterator>
- #include <type_traits>
- /*
- * Obojsmerny iterator ktory zoskupuje rozne iteratory z roznych kontainerov
- */
- namespace abu{
- template <class... Is>
- class multi_iterator : public std::tuple<Is...>{
- public:
- using base = std::tuple<Is...>;
- using tuple = base;
- template<size_t N>
- using iterator_n = typename std::tuple_element<N, tuple>::type;
- using iterator_category = std::bidirectional_iterator_tag;
- using value_type = multi_iterator;
- using reference = value_type&;
- using pointer = value_type*;
- using const_reference = const reference;
- using const_pointer = const pointer;
- private:
- template<class Tuple, size_t N>
- struct Move{
- static inline void next(Tuple& iters){
- ++(std::get<N>(iters));
- Move<Tuple, N-1>::next(iters);
- }
- static inline void prev(Tuple& iters){
- --(std::get<N>(iters));
- Move<Tuple, N-1>::prev(iters);
- }
- };
- template<class Tuple>
- struct Move<Tuple, 0>{
- static inline void next(Tuple& iters){++(std::get<0>(iters));}
- static inline void prev(Tuple& iters){--(std::get<0>(iters));}
- };
- void next(){Move<tuple, std::tuple_size<tuple>::value-1>::next(*this);}
- void prev(){Move<tuple, std::tuple_size<tuple>::value-1>::prev(*this);}
- public:
- multi_iterator& operator++(){this->next();return *this;}
- multi_iterator& operator++(int){this->next();return *this;}
- multi_iterator& operator--(){this->prev();return *this;}
- multi_iterator& operator--(int){this->prev();return *this;}
- template<size_t N>
- iterator_n<N>& get(){return std::get<N>(*this);}
- template<size_t N>
- const iterator_n<N>& get()const{return std::get<N>(*this);}
- template<size_t N>
- const iterator_n<N>& cget()const{return std::get<N>(*this);}
- reference operator*(){return *this;}
- const_reference operator*()const{return *this;}
- multi_iterator(){}
- multi_iterator(tuple&& t):base(std::move(t)){}
- multi_iterator(const tuple& t):base(t){}
- multi_iterator(Is... is):base(is...){}
- };
- template <class... Is>
- multi_iterator<Is...> make_multi_iterator(Is... is){return multi_iterator<Is...>(is...);}
- template <class... Is>
- multi_iterator<Is...> make_multi_iterator(const std::tuple<Is...>& tuple){return multi_iterator<Is...>(tuple);}
- template <class... Is>
- multi_iterator<Is...> make_multi_iterator(std::tuple<Is...>&& tuple){return multi_iterator<Is...>(std::move(tuple));}
- /*
- * pair ktory obsahuje iteratory, na kontainer <first, second) a tvari sa ako container (ma metody begin a end)
- */
- template <class Iterator>
- struct range : public std::pair<Iterator, Iterator>{
- public:
- using pair = std::pair<Iterator, Iterator>;
- using iterator = Iterator;
- public:
- iterator& begin(){return this->pair::first;}
- const iterator& begin()const{return this->pair::first;}
- const iterator& cbegin()const{return this->pair::first;}
- iterator& end(){return this->pair::second;}
- const iterator& end()const{return this->pair::second;}
- const iterator& cend()const{return this->pair::second;}
- range(const range& ) = default;
- range(const pair& p):pair(p){}
- range(iterator b, iterator e):pair(b, e){}
- };
- template <class Iterator>
- range<Iterator> make_range(Iterator b, Iterator e){return range<Iterator>(b, e);}
- template <class Iterator>
- range<Iterator> make_range(const std::pair<Iterator, Iterator>& pair){return range<Iterator>(pair);}
- /*
- *
- */
- template <class... Is>
- struct multi_iterator_range : public range<multi_iterator<Is...>>{
- using base = range<multi_iterator<Is...>>;
- using pair = typename base::pair;
- using iterator = typename base::iterator;
- using tuple = typename base::iterator::tuple;
- template<size_t N>
- using iterator_n = multi_iterator<Is...>::iterator_n<N>;
- using base::begin;
- using base::cbegin;
- using base::end;
- using base::cend;
- template<size_t N>iterator_n<N>& begin(){return std::get<N>(this->begin());}
- template<size_t N>const iterator_n<N>& begin()const{return std::get<N>(this->begin());}
- template<size_t N>const iterator_n<N>& cbegin()const{return std::get<N>(this->begin());}
- template<size_t N>iterator_n<N>& end(){return std::get<N>(this->end());}
- template<size_t N>const iterator_n<N>& end()const{return std::get<N>(this->end());}
- template<size_t N>const iterator_n<N>& cend()const{return std::get<N>(this->end());}
- multi_iterator_range(const multi_iterator_range& ) = default;
- multi_iterator_range(const base& r):base(r){}
- multi_iterator_range(const pair& p):base(p){}
- multi_iterator_range(iterator b, iterator e):base(b, e){}
- };
- template <class... Cs>
- auto make_multi_iterator_range(Cs&... cs) -> multi_iterator_range<decltype(std::begin(cs))...>{
- return multi_iterator_range<decltype(std::begin(cs))...>(
- make_multi_iterator(std::begin(cs)...),
- make_multi_iterator(std::end(cs)...)
- );
- }
- template <class... Is>
- multi_iterator_range<Is...> make_multi_iterator_range(const multi_iterator<Is...>& b, const multi_iterator<Is...>& e){
- return {b, e};
- }
- } /* namespace abu */
- #include <vector>
- #include <list>
- #include <unordered_set>
- #include <algorithm>
- int main(){
- std::vector<int> a{4, 3, 2, 1};
- std::list<char> b{'a', 'b', 'c', 'd'};
- std::unordered_set<std::string> c{"Boo", "Minsc", "Aladin", "Ehmm"};
- using namespace abu;
- auto r = make_multi_iterator_range(a, b, c);
- for(auto i = r.begin(); i != r.end() ; ++i){
- /*
- * Toto je neefektivne lebo sa v podmienke porovnavaju vsetky iteratory
- */
- std::cout
- << "["
- << *i.get<0>()
- << ", "
- << *i.get<1>()
- << ", "
- << *i.get<2>()
- << "]\n"
- ;
- }
- std::cout << "-------------------------------------------------------------------\n";
- for(auto& i : make_multi_iterator_range(c, b, a)){
- /*
- * Toto je neefektivne lebo sa v podmienke porovnavaju vsetky iteratory
- * i je iterator lebo multi_iterator::operator*() vracia (*this) :)
- */
- std::cout
- << "["
- << *i.get<0>()
- << ", "
- << *i.get<1>()
- << ", "
- << *i.get<2>()
- << "]\n"
- ;
- }
- std::cout << "-------------------------------------------------------------------\n";
- for(auto i = r.begin(); i.get<0>() != r.end<0>() ; ++i){
- /*
- * Staci porovnat 1 iterator
- */
- std::cout
- << "["
- << *i.get<0>()
- << ", "
- << *i.get<1>()
- << ", "
- << *i.get<2>()
- << "]\n"
- ;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement