ZipPair.h
Go to the documentation of this file.
1 /*!
2  *
3  *
4  * \brief Range which zips two ranges together while allowing a custom pair type
5  *
6  *
7  *
8  *
9  * \author Oswin Krause
10  * \date 2012
11  *
12  *
13  * \par Copyright 1995-2015 Shark Development Team
14  *
15  * <BR><HR>
16  * This file is part of Shark.
17  * <http://image.diku.dk/shark/>
18  *
19  * Shark is free software: you can redistribute it and/or modify
20  * it under the terms of the GNU Lesser General Public License as published
21  * by the Free Software Foundation, either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * Shark is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU Lesser General Public License for more details.
28  *
29  * You should have received a copy of the GNU Lesser General Public License
30  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
33 #ifndef SHARK_CORE_ZIPPAIR_H
34 #define SHARK_CORE_ZIPPAIR_H
35 
37 #include "Impl/boost_iterator_facade_fixed.hpp"//thanks, boost.
38 
39 #include <utility>
40 
41 namespace shark{
42 
43 ///\brief Given a type of pair and two iterators to zip together, returns the reference
44 ///
45 ///e.g. for std::pair<T,U> the reference is std::pair<T&,U&>
46 template<class Pair, class Iterator1, class Iterator2>
48 
49 /// \cond
50 
51 template<class T, class U,class Iterator1, class Iterator2>
52 struct PairReference<std::pair<T, U>, Iterator1, Iterator2 >{
53  typedef std::pair<
54  typename boost::iterator_reference<Iterator1>::type,
55  typename boost::iterator_reference<Iterator2>::type
56  > type;
57 };
58 
59 /// \endcond
60 
61 ///\brief A Pair-Iterator which gives a unified view of two ranges.
62 ///
63 /// A Pair-Iterator is an iterator which zips two ranges together and returns the zipped result.
64 /// This implementation allows the return type to be an arbirtrary Pair which is then constructed using
65 /// Reference(*iter1,*iter2) when the iterator is dereferenced. This allows for more expressive element access
66 /// instead of iter->first or iter->second.
67 /// \todo Both underlying Iterators must be random access iterators.
68 //todo: implement as decorator for boost::zip_iterator
69 template<class Value,class Iterator1,class Iterator2>
70 class PairIterator: public SHARK_ITERATOR_FACADE<
71  PairIterator<Value,Iterator1,Iterator2>,
72  Value,
73  std::random_access_iterator_tag,
74  typename PairReference<Value,Iterator1,Iterator2>::type
75 >{
76 private:
77  typedef typename PairReference<Value,Iterator1,Iterator2>::type Reference;
78  template<class,class,class> friend class PairIterator;
79 public:
81 
82  ///\brief Copy-Constructs this iterator from some other IndexedIterator convertible to this.
83  template< class IteratorT1,class IteratorT2>
84  PairIterator(IteratorT1 const& iterator1, IteratorT2 const& iterator2)
85  : m_iterator1(iterator1),m_iterator2(iterator2){}
86 
87  template<class V,class I1,class I2>
89  : m_iterator1(iterator.m_iterator1),m_iterator2(iterator.m_iterator2){}
90 
91  Iterator1 first()const{
92  return m_iterator1;
93  }
94 
95  Iterator2 second()const{
96  return m_iterator2;
97  }
98 
99  std::pair<Iterator1,Iterator2> iterators()const{
100  return std::make_pair(m_iterator1,m_iterator2);
101  }
102 
103 private:
104  friend class SHARK_ITERATOR_CORE_ACCESS;
105 
106  void increment() {
107  ++m_iterator1;
108  ++m_iterator2;
109  }
110  void decrement() {
111  --m_iterator1;
112  --m_iterator2;
113  }
114 
115  void advance(std::ptrdiff_t n){
116  m_iterator1 += n;
117  m_iterator2 += n;
118  }
119 
120  template<class V,class I1,class I2>
121  std::ptrdiff_t distance_to(PairIterator<V,I1,I2> const& other) const{
122  return other.m_iterator1 - m_iterator1;
123  }
124 
125  template<class V,class I1,class I2>
126  bool equal(PairIterator<V,I1,I2> const& other) const{
127  return m_iterator1 == other.m_iterator1;
128  }
129  Reference dereference() const {
130  return Reference(*m_iterator1,*m_iterator2);
131  }
132 
133  Iterator1 m_iterator1;
134  Iterator2 m_iterator2;
135 };
136 
137 ///\brief returns a paired zip range using pair type Pair
138 ///This class must be specialized for every Pair to be used
139 template<class PairType, class Iterator1, class Iterator2>
140 boost::iterator_range<
142 >
143 zipPairRange(Iterator1 begin1, Iterator1 end1, Iterator2 begin2,Iterator2 end2){
145  return boost::make_iterator_range(iterator(begin1,begin2),iterator(end1,end2));
146 }
147 
148 template<class PairType, class Range1, class Range2>
150  typedef boost::iterator_range<
151  PairIterator<
152  PairType,
153  typename boost::range_iterator<Range1>::type,
154  typename boost::range_iterator<Range2>::type
155  >
156  > type;
157 };
158 
159 ///\brief returns a paired zip range using pair type Pair
160 ///
161 /// usage: zipPairRange<PairType>(range1,range2) leads to a range consisting
162 /// where the i-th element is the Pair PairType(range1[i],range2[i]).
163 template<class PairType, class Range1, class Range2>
164 typename PairRangeType<PairType, Range1, Range2>::type
165 zipPairRange(Range1 & range1, Range2& range2){
166  return zipPairRange<PairType>(boost::begin(range1), boost::end(range1), boost::begin(range2),boost::end(range2));
167 }
168 
169 
170 
171 ///\brief returns a paired zip range using pair type Pair
172 ///
173 /// usage: zipPairRange<PairType>(range1,range2) leads to a range consisting
174 /// where the i-th element is the Pair PairType(range1[i],range2[i]).
175 template<class PairType, class Range1, class Range2>
176 typename PairRangeType<PairType, Range1 const, Range2 const>::type
177 zipPairRange(Range1 const& range1, Range2 const& range2){
178  return zipPairRange<PairType>(boost::begin(range1), boost::end(range1), boost::begin(range2),boost::end(range2));
179 }
180 
181 }
182 #endif