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

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

adding default constructor in StrideIterator?

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
1#ifndef _theplu_yat_utility_stride_iterator_
2#define _theplu_yat_utility_stride_iterator_
3
4// $Id: StrideIterator.h 1378 2008-07-16 20:57:44Z 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 default constructor
114
115       Using default constructor of BASE iterator.
116     */
117    StrideIterator(difference_type stride=1)
118      : stride_(stride) {}
119
120    /**
121       \brief Constructor
122    */
123    explicit StrideIterator(Iter p, difference_type stride=1)
124      : iterator_(p), stride_(stride) {}
125
126   
127    /**
128       Conversion from mutable iterator to const iterator. Only works
129       if underlying iterator is a pointer.
130     */
131    // Peter, this is ugly hack to provide iterator to const_iterator
132    // for our gsl_iterators - solution? use Boost:iterator_adaptor
133    operator StrideIterator<const value_type*>()
134    { return StrideIterator<const value_type*>(base(), stride_); }
135
136    /**
137       \return underlying iterator
138     */
139    inline Iter base(void) const { return iterator_; }
140
141    /**
142       \return stride
143     */
144    inline size_t stride(void) const { return stride_; }
145
146    /**
147       \return element
148     */
149    reference operator*(void) const 
150    { return *iterator_; }
151
152    /**
153       \return pointer
154     */
155    pointer operator->() const { return &(operator*()); }
156
157    /**
158       \return element \a n steps forward
159     */
160    reference operator[](difference_type n) const 
161    { 
162      return iterator_[stride_*n];
163    }
164
165    /**
166       \brief pre-increment
167
168       \return reference to *this
169     */
170    StrideIterator& operator++(void) { iterator_+=stride_; return *this; }
171
172    /**
173       \brief post-increment
174
175       \return copy of iterator prior increment
176     */
177    StrideIterator operator++(int) 
178    { StrideIterator tmp(*this); iterator_+=stride_; return tmp;}
179
180    /**
181       \brief iterate \f$ n \f$ steps forward
182
183       \return reference to resulting iterator
184     */
185    StrideIterator& operator+=(int n) { iterator_+=stride_*n; return *this; }
186
187    /**
188       \brief post-decrement
189
190       \return copy of iterator prior decrement
191     */
192    StrideIterator operator--(int) 
193    { StrideIterator tmp(*this); iterator_-=stride_; return tmp;}
194
195    /**
196       \brief pre-decrement
197
198       \return reference to resulting iterator
199     */
200    StrideIterator& operator--(void) { iterator_-=stride_; return *this; }
201
202    /**
203       \brief iterate \f$ n \f$ steps backwards
204
205       \return reference to resulting iterator
206     */
207    StrideIterator& operator-=(int n) { iterator_-=n*stride_; return *this; }
208
209    /**
210       \brief addition operator
211
212       \return copy of resulting iterator
213     */
214    friend StrideIterator operator+(const StrideIterator& lhs,difference_type n) 
215    { StrideIterator tmp(lhs); tmp+=n; return tmp; }
216
217    /**
218       \brief subtraction operator
219
220       \return copy of resulting iterator
221     */
222    friend StrideIterator operator-(const StrideIterator& lhs, 
223                                    difference_type n) 
224    { StrideIterator tmp(lhs); tmp-=n; return tmp; }
225
226    /**
227       \brief difference operator
228
229       \return distance between \a lhs and \a rhs
230     */
231    friend difference_type operator-(const StrideIterator& lhs, 
232                                     const StrideIterator& rhs) 
233    {
234      yat_assert<std::runtime_error>(lhs.stride_==rhs.stride_, 
235        "StrideIterator::operator- different stride in lhs and rhs.");
236      return static_cast<difference_type>( (lhs.iterator_-rhs.iterator_)/
237                                           lhs.stride_);
238    }
239
240   
241    /**
242       \brief Equality operator
243
244       \return True 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 Non-equality operator
251
252       \return False if \a lhs and \a rhs are pointing to same element
253     */
254    friend bool operator!=(const StrideIterator& lhs, const StrideIterator& rhs)
255    { return lhs.iterator_!=rhs.iterator_; }
256   
257    /**
258       \brief Less operator
259     */
260    friend bool operator<(const StrideIterator& lhs, const StrideIterator& rhs)
261    { return lhs.iterator_<rhs.iterator_; }
262   
263    /**
264       \brief Less equal operator
265     */
266    friend bool operator<=(const StrideIterator& lhs, const StrideIterator& rhs)
267    { return lhs.iterator_<=rhs.iterator_; }
268   
269    /**
270       \brief Larger operator
271     */
272    friend bool operator>(const StrideIterator& lhs, const StrideIterator& rhs)
273    { return lhs.iterator_>rhs.iterator_; }
274   
275    /**
276       \brief Larger equal operator
277     */
278    friend bool operator>=(const StrideIterator& lhs, const StrideIterator& rhs)
279    { return lhs.iterator_>=rhs.iterator_; }
280   
281  private:
282    Iter iterator_;
283    size_t stride_;
284
285    // Using compiler generated copy
286    //StrideIterator(const StrideIterator&);
287    //StrideIterator& operator=(const StrideIterator&);
288  };
289
290
291
292
293
294}}} // of namespace utility, yat, and theplu
295
296#endif
Note: See TracBrowser for help on using the repository browser.