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

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

fixes #402 - constness conversion in StrideIterator?

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.8 KB
Line 
1#ifndef _theplu_yat_utility_stride_iterator_
2#define _theplu_yat_utility_stride_iterator_
3
4// $Id: StrideIterator.h 1386 2008-07-22 20:18:51Z 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 <boost/iterator/iterator_adaptor.hpp>
32
33#include <iterator>
34#include <stdexcept>
35
36namespace theplu {
37namespace yat {
38namespace utility {
39
40  // forward declaration
41  template<typename Iter>
42  class StrideIterator;
43
44  /**
45     Specialization for StrideIterator that calls underlying iterator.
46   */
47  template <typename Iter>
48  struct weighted_iterator_traits<StrideIterator<Iter> > {
49    /**
50       StrideIterator is weighted if underlying iterator is weighted.
51    */
52    typedef typename weighted_iterator_traits<Iter>::type type;
53  };
54
55  /**
56     Specialization for StrideIterator using iterator_traits with base()
57   */
58  template <class Iter>
59  struct iterator_traits<StrideIterator<Iter> > {
60    /**
61       data_reference same as for underlying iterator
62     */
63    typedef typename iterator_traits<Iter>::data_reference data_reference;
64
65    /**
66       weight_reference same as for underlying iterator
67     */
68    typedef typename iterator_traits<Iter>::weight_reference weight_reference;
69
70    /**
71       \return data of iterator
72    */
73    data_reference data(StrideIterator<Iter> iter) const 
74    { return iterator_traits<Iter>().data(iter.base()); }
75
76    /**
77       \return weight of iterator
78    */
79    weight_reference weight(StrideIterator<Iter> iter) const 
80    { return iterator_traits<Iter>().weight(iter.base()); }
81
82  };
83
84  /**
85     @brief Adaptor using a stride on underlying iterator
86
87     Works as underlying iterator except that all arithmetic uses the
88     stride, so e.g., ++StrideIterator returns underlying
89     _iterator+stride
90
91  */
92  template<typename Iter>
93  class StrideIterator 
94    : public std::iterator<typename std::iterator_traits<Iter>::iterator_category, 
95                           typename std::iterator_traits<Iter>::value_type, 
96                           typename std::iterator_traits<Iter>::difference_type, 
97                           typename std::iterator_traits<Iter>::pointer, 
98                           typename std::iterator_traits<Iter>::reference>
99  {
100  public:
101    /// type of underlying iterator
102    typedef Iter iterator_type;
103    /// value type
104    typedef typename std::iterator_traits<Iter>::value_type value_type;
105    /// difference type
106    typedef typename std::iterator_traits<Iter>::difference_type difference_type;
107    /// reference
108    typedef typename std::iterator_traits<Iter>::reference reference;
109    /// pointer
110    typedef typename std::iterator_traits<Iter>::pointer pointer;
111    /// weighted_iterator_tag if iterator is weighted
112    typedef typename yat::utility::weighted_iterator_traits<Iter>::type w_type;
113
114    /**
115       \brief default constructor
116
117       Using default constructor of BASE iterator.
118     */
119    StrideIterator(difference_type stride=1)
120      : stride_(stride) {}
121
122    /**
123       \brief Constructor
124    */
125    explicit StrideIterator(Iter p, difference_type stride=1)
126      : iterator_(p), stride_(stride) {}
127
128   
129    /**
130       \brief Conversion constructor.
131
132       Create a StrideIterator<Iter> from a StrideIterator<I2>. Possible
133       if I2 is convertible to a Iter. Constructor allows implicit
134       conversions such as iterator to const_iterator.
135     */
136    template<typename I2>
137    StrideIterator(StrideIterator<I2> other,
138                   typename boost::enable_if_convertible<I2, Iter>::type* = 0 )
139      : iterator_(other.base()), stride_(other.stride()) {}
140
141    /**
142       \return underlying iterator
143     */
144    inline Iter base(void) const { return iterator_; }
145
146    /**
147       \return stride
148     */
149    inline size_t stride(void) const { return stride_; }
150
151    /**
152       \return element
153     */
154    reference operator*(void) const 
155    { return *iterator_; }
156
157    /**
158       \return pointer
159     */
160    pointer operator->() const { return &(operator*()); }
161
162    /**
163       \return element \a n steps forward
164     */
165    reference operator[](difference_type n) const 
166    { 
167      return iterator_[stride_*n];
168    }
169
170    /**
171       \brief pre-increment
172
173       \return reference to *this
174     */
175    StrideIterator& operator++(void) { iterator_+=stride_; return *this; }
176
177    /**
178       \brief post-increment
179
180       \return copy of iterator prior increment
181     */
182    StrideIterator operator++(int) 
183    { StrideIterator tmp(*this); iterator_+=stride_; return tmp;}
184
185    /**
186       \brief iterate \f$ n \f$ steps forward
187
188       \return reference to resulting iterator
189     */
190    StrideIterator& operator+=(int n) { iterator_+=stride_*n; return *this; }
191
192    /**
193       \brief post-decrement
194
195       \return copy of iterator prior decrement
196     */
197    StrideIterator operator--(int) 
198    { StrideIterator tmp(*this); iterator_-=stride_; return tmp;}
199
200    /**
201       \brief pre-decrement
202
203       \return reference to resulting iterator
204     */
205    StrideIterator& operator--(void) { iterator_-=stride_; return *this; }
206
207    /**
208       \brief iterate \f$ n \f$ steps backwards
209
210       \return reference to resulting iterator
211     */
212    StrideIterator& operator-=(int n) { iterator_-=n*stride_; return *this; }
213
214    /**
215       \brief addition operator
216
217       \return copy of resulting iterator
218     */
219    friend StrideIterator operator+(const StrideIterator& lhs,difference_type n) 
220    { StrideIterator tmp(lhs); tmp+=n; return tmp; }
221
222    /**
223       \brief subtraction operator
224
225       \return copy of resulting iterator
226     */
227    friend StrideIterator operator-(const StrideIterator& lhs, 
228                                    difference_type n) 
229    { StrideIterator tmp(lhs); tmp-=n; return tmp; }
230
231    /**
232       \brief difference operator
233
234       \return distance between \a lhs and \a rhs
235     */
236    friend difference_type operator-(const StrideIterator& lhs, 
237                                     const StrideIterator& rhs) 
238    {
239      yat_assert<std::runtime_error>(lhs.stride_==rhs.stride_, 
240        "StrideIterator::operator- different stride in lhs and rhs.");
241      return static_cast<difference_type>( (lhs.iterator_-rhs.iterator_)/
242                                           lhs.stride_);
243    }
244
245   
246    /**
247       \brief Equality operator
248
249       \return True if \a lhs and \a rhs are pointing to same element
250     */
251    friend bool operator==(const StrideIterator& lhs, const StrideIterator& rhs)
252    { return lhs.iterator_==rhs.iterator_; }
253   
254    /**
255       \brief Non-equality operator
256
257       \return False if \a lhs and \a rhs are pointing to same element
258     */
259    friend bool operator!=(const StrideIterator& lhs, const StrideIterator& rhs)
260    { return lhs.iterator_!=rhs.iterator_; }
261   
262    /**
263       \brief Less operator
264     */
265    friend bool operator<(const StrideIterator& lhs, const StrideIterator& rhs)
266    { return lhs.iterator_<rhs.iterator_; }
267   
268    /**
269       \brief Less equal operator
270     */
271    friend bool operator<=(const StrideIterator& lhs, const StrideIterator& rhs)
272    { return lhs.iterator_<=rhs.iterator_; }
273   
274    /**
275       \brief Larger operator
276     */
277    friend bool operator>(const StrideIterator& lhs, const StrideIterator& rhs)
278    { return lhs.iterator_>rhs.iterator_; }
279   
280    /**
281       \brief Larger equal operator
282     */
283    friend bool operator>=(const StrideIterator& lhs, const StrideIterator& rhs)
284    { return lhs.iterator_>=rhs.iterator_; }
285   
286  private:
287    Iter iterator_;
288    size_t stride_;
289
290    // Using compiler generated copy
291    //StrideIterator(const StrideIterator&);
292    //StrideIterator& operator=(const StrideIterator&);
293  };
294
295
296
297
298
299}}} // of namespace utility, yat, and theplu
300
301#endif
Note: See TracBrowser for help on using the repository browser.