source: trunk/yat/utility/StrideIterator.h @ 1374

Last change on this file since 1374 was 1374, checked in by Peter, 13 years ago

fixes #391 - implemented specializations for StrideIterator? and Container2DIterator

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.5 KB
Line 
1#ifndef _theplu_yat_utility_stride_iterator_
2#define _theplu_yat_utility_stride_iterator_
3
4// $Id: StrideIterator.h 1374 2008-07-16 16:34:45Z peter $
5
6/*
7  Copyright (C) 2007 Jari Häkkinen, Peter Johansson
8  Copyright (C) 2008 Peter Johansson
9
10  This file is part of the yat library, http://trac.thep.lu.se/yat
11
12  The yat library is free software; you can redistribute it and/or
13  modify it under the terms of the GNU General Public License as
14  published by the Free Software Foundation; either version 2 of the
15  License, or (at your option) any later version.
16
17  The yat library is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  General Public License for more details.
21
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25  02111-1307, USA.
26*/
27
28#include "iterator_traits.h"
29#include "yat_assert.h"
30
31#include <iterator>
32#include <stdexcept>
33
34namespace theplu {
35namespace yat {
36namespace utility {
37
38  // forward declaration
39  template<typename Iter>
40  class StrideIterator;
41
42  /**
43     Specialization for StrideIterator that calls underlying iterator.
44   */
45  template <typename Iter>
46  struct weighted_iterator_traits<StrideIterator<Iter> > {
47    /**
48       StrideIterator is weighted if underlying iterator is weighted.
49    */
50    typedef typename weighted_iterator_traits<Iter>::type type;
51  };
52
53  /**
54     Specialization for StrideIterator using iterator_traits with base()
55   */
56  template <class Iter>
57  struct iterator_traits<StrideIterator<Iter> > {
58    /**
59       data_reference same as for underlying iterator
60     */
61    typedef typename iterator_traits<Iter>::data_reference data_reference;
62
63    /**
64       weight_reference same as for underlying iterator
65     */
66    typedef typename iterator_traits<Iter>::weight_reference weight_reference;
67
68    /**
69       \return data of iterator
70    */
71    data_reference data(StrideIterator<Iter> iter) const 
72    { return iterator_traits<Iter>().data(iter.base()); }
73
74    /**
75       \return weight of iterator
76    */
77    weight_reference weight(StrideIterator<Iter> iter) const 
78    { return iterator_traits<Iter>().weight(iter.base()); }
79
80  };
81
82  /**
83     @brief Adaptor using a stride on underlying iterator
84
85     Works as underlying iterator except that all arithmetic uses the
86     stride, so e.g., ++StrideIterator returns underlying
87     _iterator+stride
88
89  */
90  template<typename Iter>
91  class StrideIterator 
92    : public std::iterator<typename std::iterator_traits<Iter>::iterator_category, 
93                           typename std::iterator_traits<Iter>::value_type, 
94                           typename std::iterator_traits<Iter>::difference_type, 
95                           typename std::iterator_traits<Iter>::pointer, 
96                           typename std::iterator_traits<Iter>::reference>
97  {
98  public:
99    /// type of underlying iterator
100    typedef Iter iterator_type;
101    /// value type
102    typedef typename std::iterator_traits<Iter>::value_type value_type;
103    /// difference type
104    typedef typename std::iterator_traits<Iter>::difference_type difference_type;
105    /// reference
106    typedef typename std::iterator_traits<Iter>::reference reference;
107    /// pointer
108    typedef typename std::iterator_traits<Iter>::pointer pointer;
109    /// weighted_iterator_tag if iterator is weighted
110    typedef typename yat::utility::weighted_iterator_traits<Iter>::type w_type;
111
112    /**
113       \brief Constructor
114    */
115    explicit StrideIterator(Iter p, difference_type stride=1)
116      : iterator_(p), stride_(stride) {}
117
118   
119    /**
120       Conversion from mutable iterator to const iterator. Only works
121       if underlying iterator is a pointer.
122     */
123    // Peter, this is ugly hack to provide iterator to const_iterator
124    // for our gsl_iterators - solution? use Boost:iterator_adaptor
125    operator StrideIterator<const value_type*>()
126    { return StrideIterator<const value_type*>(base(), stride_); }
127
128    /**
129       \return underlying iterator
130     */
131    inline Iter base(void) const { return iterator_; }
132
133    /**
134       \return stride
135     */
136    inline size_t stride(void) const { return stride_; }
137
138    /**
139       \return element
140     */
141    reference operator*(void) const 
142    { return *iterator_; }
143
144    /**
145       \return pointer
146     */
147    pointer operator->() const { return &(operator*()); }
148
149    /**
150       \return element \a n steps forward
151     */
152    reference operator[](difference_type n) const 
153    { 
154      return iterator_[stride_*n];
155    }
156
157    /**
158       \brief pre-increment
159
160       \return reference to *this
161     */
162    StrideIterator& operator++(void) { iterator_+=stride_; return *this; }
163
164    /**
165       \brief post-increment
166
167       \return copy of iterator prior increment
168     */
169    StrideIterator operator++(int) 
170    { StrideIterator tmp(*this); iterator_+=stride_; return tmp;}
171
172    /**
173       \brief iterate \f$ n \f$ steps forward
174
175       \return reference to resulting iterator
176     */
177    StrideIterator& operator+=(int n) { iterator_+=stride_*n; return *this; }
178
179    /**
180       \brief post-decrement
181
182       \return copy of iterator prior decrement
183     */
184    StrideIterator operator--(int) 
185    { StrideIterator tmp(*this); iterator_-=stride_; return tmp;}
186
187    /**
188       \brief pre-decrement
189
190       \return reference to resulting iterator
191     */
192    StrideIterator& operator--(void) { iterator_-=stride_; return *this; }
193
194    /**
195       \brief iterate \f$ n \f$ steps backwards
196
197       \return reference to resulting iterator
198     */
199    StrideIterator& operator-=(int n) { iterator_-=n*stride_; return *this; }
200
201    /**
202       \brief addition operator
203
204       \return copy of resulting iterator
205     */
206    friend StrideIterator operator+(const StrideIterator& lhs,difference_type n) 
207    { StrideIterator tmp(lhs); tmp+=n; return tmp; }
208
209    /**
210       \brief subtraction operator
211
212       \return copy of resulting iterator
213     */
214    friend StrideIterator operator-(const StrideIterator& lhs, 
215                                    difference_type n) 
216    { StrideIterator tmp(lhs); tmp-=n; return tmp; }
217
218    /**
219       \brief difference operator
220
221       \return distance between \a lhs and \a rhs
222     */
223    friend difference_type operator-(const StrideIterator& lhs, 
224                                     const StrideIterator& rhs) 
225    {
226      yat_assert<std::runtime_error>(lhs.stride_==rhs.stride_, 
227        "StrideIterator::operator- different stride in lhs and rhs.");
228      return static_cast<difference_type>( (lhs.iterator_-rhs.iterator_)/
229                                           lhs.stride_);
230    }
231
232   
233    /**
234       \brief Equality operator
235
236       \return True if \a lhs and \a rhs are pointing to same element
237     */
238    friend bool operator==(const StrideIterator& lhs, const StrideIterator& rhs)
239    { return lhs.iterator_==rhs.iterator_; }
240   
241    /**
242       \brief Non-equality operator
243
244       \return False if \a lhs and \a rhs are pointing to same element
245     */
246    friend bool operator!=(const StrideIterator& lhs, const StrideIterator& rhs)
247    { return lhs.iterator_!=rhs.iterator_; }
248   
249    /**
250       \brief Less operator
251     */
252    friend bool operator<(const StrideIterator& lhs, const StrideIterator& rhs)
253    { return lhs.iterator_<rhs.iterator_; }
254   
255    /**
256       \brief Less equal operator
257     */
258    friend bool operator<=(const StrideIterator& lhs, const StrideIterator& rhs)
259    { return lhs.iterator_<=rhs.iterator_; }
260   
261    /**
262       \brief Larger operator
263     */
264    friend bool operator>(const StrideIterator& lhs, const StrideIterator& rhs)
265    { return lhs.iterator_>rhs.iterator_; }
266   
267    /**
268       \brief Larger equal operator
269     */
270    friend bool operator>=(const StrideIterator& lhs, const StrideIterator& rhs)
271    { return lhs.iterator_>=rhs.iterator_; }
272   
273  private:
274    Iter iterator_;
275    size_t stride_;
276
277    // Using compiler generated copy
278    //StrideIterator(const StrideIterator&);
279    //StrideIterator& operator=(const StrideIterator&);
280  };
281
282
283
284
285
286}}} // of namespace utility, yat, and theplu
287
288#endif
Note: See TracBrowser for help on using the repository browser.